Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ CLOUDFLARE_API_TOKEN= # Workers + Pages edit, D1,

# ── React Bits Pro (only if using its components) ───────────────────────────
REACTBITS_LICENSE_KEY=

# --- Walrus Harbor (Seal-encrypted storage on Sui testnet) ---
HARBOR_BASE_URL=https://api.testnet.harbor.walrus.xyz
HARBOR_API_KEY=hbr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HARBOR_SERVICE_PRIVATE_KEY=suiprivkey1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HARBOR_DEFAULT_SPACE_ID=
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ coverage/
runs/
artifacts/
*.tsbuildinfo

# Cloudflare local secrets
.dev.vars
7 changes: 5 additions & 2 deletions apps/api/cloudflare/wrangler.example.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"compatibility_flags": ["nodejs_compat"],
"main": "../src/worker.ts",
"vars": {
"CONTEXTMEM_WORKER_BASE_URL": "http://localhost:8787"
"CONTEXTMEM_WORKER_BASE_URL": "http://localhost:8787",
"HARBOR_BASE_URL": "https://api.testnet.harbor.walrus.xyz",
"HARBOR_DEFAULT_SPACE_ID": "replace-with-harbor-space-id"
},
"d1_databases": [
{
Expand Down Expand Up @@ -34,6 +36,7 @@
]
},
"secrets": {
"required": ["CONTEXTMEM_NAMESPACE_IMPORT_TOKEN", "FIRECRAWL_API_KEY", "MEMWAL_ACCOUNT_ID", "MEMWAL_API_URL", "MEMWAL_PRIVATE_KEY"]
"required": ["CONTEXTMEM_NAMESPACE_IMPORT_TOKEN", "FIRECRAWL_API_KEY", "MEMWAL_ACCOUNT_ID", "MEMWAL_API_URL", "MEMWAL_PRIVATE_KEY"],
"harbor": ["HARBOR_API_KEY", "HARBOR_SERVICE_PRIVATE_KEY"]
}
}
24 changes: 24 additions & 0 deletions apps/api/migrations/0007_harbor_namespace_storage.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- Harbor (Walrus) private storage for namespaces.
-- PRIVATE namespaces are Seal-encrypted in the Worker and their ciphertext is
-- stored in a per-namespace Harbor bucket instead of plaintext R2. All columns
-- are nullable so existing/public artifacts (r2_key only, no harbor_file_id)
-- keep working unchanged. D1/SQLite requires one ALTER per statement.

-- Per-namespace Harbor bucket + Seal policy (resolved/created once, reused across versions).
ALTER TABLE contextmem_namespaces ADD COLUMN harbor_space_id TEXT;
ALTER TABLE contextmem_namespaces ADD COLUMN harbor_bucket_id TEXT;
ALTER TABLE contextmem_namespaces ADD COLUMN harbor_seal_policy_id TEXT;

-- StorageProvider seam (#19): which backend holds this namespace's artifacts
-- ('harbor' = private/encrypted, NULL or 'r2' = public/plaintext), and the
-- per-namespace Seal identity salt (32-byte nonce, hex) so the encryption identity
-- stays stable across versions. Nullable so existing namespaces keep working.
ALTER TABLE contextmem_namespaces ADD COLUMN storage_provider TEXT;
ALTER TABLE contextmem_namespaces ADD COLUMN seal_identity_salt TEXT;

-- Per-artifact Harbor file pointer. When set, the read path decrypts from Harbor
-- and ignores r2_key (which holds a `harbor:<fileId>` sentinel to satisfy NOT NULL).
ALTER TABLE contextmem_namespace_artifacts ADD COLUMN harbor_file_id TEXT;
ALTER TABLE contextmem_namespace_artifacts ADD COLUMN harbor_bucket_id TEXT;

CREATE INDEX IF NOT EXISTS contextmem_artifacts_harbor_idx ON contextmem_namespace_artifacts(harbor_bucket_id, harbor_file_id);
33 changes: 33 additions & 0 deletions apps/api/scripts/cf-virtual-stubs.preload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Bun preload: stub Cloudflare Workers virtual modules (`cloudflare:workers`,
* `cloudflare:email`) so the worker module (which transitively imports `agents`)
* can be loaded under plain Bun for the Harbor wiring smoke test. These symbols
* are never exercised by storeNamespaceImport / readArtifact — they only need to
* resolve at import-link time. Test-only; not shipped to the Worker.
*/
import { plugin } from "bun";

plugin({
name: "cf-virtual-stubs",
setup(build) {
build.module("cloudflare:workers", () => ({
loader: "object",
exports: {
DurableObject: class DurableObject {},
WorkflowEntrypoint: class WorkflowEntrypoint {},
RpcTarget: class RpcTarget {},
WorkerEntrypoint: class WorkerEntrypoint {},
exports: {},
env: {},
},
}));
build.module("cloudflare:email", () => ({
loader: "object",
exports: { EmailMessage: class EmailMessage {} },
}));
build.module("cloudflare:sockets", () => ({
loader: "object",
exports: { connect: () => { throw new Error("cloudflare:sockets stub"); } },
}));
},
});
Loading
Loading