Skip to content

Commit 133cd50

Browse files
sosweethamclaude
andcommitted
refactor(profile-editor): rebuild backend on web3-adapter for 2-way sync
Replaces the bespoke eVault-direct backend with the standard web3-adapter platform pattern, matching pictique/blabsy/dreamsync. - Local Postgres is the source of truth (users + professional_profiles). PostgresSubscriber pushes local writes to the eVault via toGlobal; POST /api/webhook ingests inbound changes via fromGlobal; AaaS is the delivery transport. lockedIds prevents echo loops. - Base identity (name/avatar/banner) syncs 2-way with all platforms via the User ontology; professional profile + the isPublic gate sync with dreamsync. - Files go to eVault blob storage via __file / EVaultClient.uploadFile (no file-manager, no bytea); the client stores the returned public URL (~20-line change: render the URL directly, drop the asset-proxy route). - Retains auth (offer/SSE/login), zod validation, and AaaS subscription bootstrap. Drops the hand-rolled GraphQL sync, search index, and bytea. The previous backend is removed; a local read-only copy was kept under reference/ and is intentionally not committed (deprecated). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 35a8c6d commit 133cd50

45 files changed

Lines changed: 1393 additions & 2483 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ PUBLIC_PROVISIONER_SHARED_SECRET="your-provisioner-shared-secret"
9797
PUBLIC_ESIGNER_BASE_URL="http://localhost:3004"
9898
PUBLIC_FILE_MANAGER_BASE_URL="http://localhost:3005"
9999
PUBLIC_PROFILE_EDITOR_BASE_URL=http://localhost:3007
100+
PROFILE_EDITOR_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/profile_editor
101+
PROFILE_EDITOR_JWT_SECRET="secret"
102+
# web3-adapter SQLite id-map directory (localId <-> eVault globalId)
103+
PROFILE_EDITOR_MAPPING_DB_PATH="/path/to/profile-editor/mapping/db"
104+
# PROFILE_EDITOR_API_PORT=3007 # optional, defaults to 3007
100105

101106
DREAMSYNC_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/dreamsync
102107
VITE_DREAMSYNC_BASE_URL="http://localhost:8888"
@@ -140,6 +145,13 @@ AWARENESS_PUBLIC_URL="http://localhost:4100"
140145
AWARENESS_INGEST_SECRET="replace-with-a-strong-secret"
141146
# Where evault-core forwards every awareness packet
142147
AWARENESS_SERVICE_URL="http://localhost:4100"
148+
# Consumer API key (aaas_...) the profile-editor backend uses to register its
149+
# webhook subscription and poll AaaS. Issued from the AaaS portal after approval.
150+
AWARENESS_API_KEY=""
151+
# Public URL AaaS should POST awareness packets to. Override for local dev
152+
# against prod AaaS — set it to your Cloudflare tunnel, e.g.
153+
# https://xyz.trycloudflare.com/api/webhook. Defaults to {base}/api/webhook.
154+
AWARENESS_WEBHOOK_URL=""
143155
# Comma-separated eNames allowed to act as AaaS portal admins
144156
AAAS_ADMIN_ENAMES=""
145157

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"watch": ["src"],
3+
"ext": "ts,json",
4+
"ignore": ["src/**/*.spec.ts"],
5+
"exec": "ts-node src/index.ts"
6+
}

platforms/profile-editor/api/package.json

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,36 @@
11
{
22
"name": "profile-editor-api",
33
"version": "1.0.0",
4-
"description": "Profile Editor API for the w3ds ecosystem",
4+
"description": "Profile Editor API for the w3ds ecosystem (AaaS-based)",
55
"main": "src/index.ts",
66
"scripts": {
77
"start": "ts-node src/index.ts",
88
"dev": "nodemon --exec ts-node src/index.ts",
9-
"build": "tsc && cp -r src/web3adapter/mappings dist/web3adapter/",
9+
"build": "tsc",
1010
"typeorm": "typeorm-ts-node-commonjs",
11-
"migration:generate": "bash -c 'read -p \"Migration name: \" name && npx typeorm-ts-node-commonjs migration:generate src/database/migrations/$name -d src/database/data-source.ts'",
12-
"migration:run": "npm run typeorm migration:run -- -d src/database/data-source.ts",
13-
"migration:revert": "npm run typeorm migration:revert -- -d src/database/data-source.ts"
11+
"migration:generate": "bash -c 'read -p \"Migration name: \" name && npx typeorm-ts-node-commonjs migration:generate src/migrations/$name -d src/db.ts'",
12+
"migration:run": "npm run typeorm migration:run -- -d src/db.ts",
13+
"migration:revert": "npm run typeorm migration:revert -- -d src/db.ts"
1414
},
1515
"dependencies": {
1616
"@metastate-foundation/auth": "workspace:*",
1717
"axios": "^1.6.7",
1818
"cors": "^2.8.5",
1919
"dotenv": "^16.4.5",
2020
"express": "^4.18.2",
21-
"form-data": "^4.0.5",
22-
"graphql-request": "^6.1.0",
23-
"jsonwebtoken": "^9.0.3",
2421
"multer": "^2.1.1",
2522
"pg": "^8.20.0",
2623
"reflect-metadata": "^0.2.2",
27-
"signature-validator": "workspace:*",
28-
"web3-adapter": "workspace:*",
2924
"typeorm": "^0.3.28",
30-
"uuid": "^9.0.1"
25+
"web3-adapter": "workspace:*",
26+
"zod": "^3.23.8"
3127
},
3228
"devDependencies": {
3329
"@types/cors": "^2.8.17",
3430
"@types/express": "^4.17.21",
35-
"@types/jsonwebtoken": "^9.0.10",
3631
"@types/multer": "^2.1.0",
3732
"@types/node": "^20.11.24",
3833
"@types/pg": "^8.18.0",
39-
"@types/uuid": "^9.0.8",
4034
"nodemon": "^3.0.3",
4135
"ts-node": "^10.9.2",
4236
"typescript": "^5.3.3"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import axios from "axios";
2+
import { env } from "./env";
3+
4+
const USER_ONTOLOGY = "550e8400-e29b-41d4-a716-446655440000";
5+
const PROFESSIONAL_PROFILE_ONTOLOGY = "550e8400-e29b-41d4-a716-446655440009";
6+
7+
/**
8+
* Registers our `/api/webhook` as an AaaS subscription for the user and
9+
* professional-profile ontologies (idempotent — skips if one already targets
10+
* us). Logs and continues on failure so a down AaaS never blocks startup.
11+
*/
12+
export async function registerSubscriptionOnStartup(): Promise<void> {
13+
if (!env.awarenessApiKey) {
14+
console.warn(
15+
"[aaas] AWARENESS_API_KEY not set — skipping subscription registration",
16+
);
17+
return;
18+
}
19+
20+
const targetUrl =
21+
env.awarenessWebhookUrl ||
22+
`${env.baseUrl.replace(/\/$/, "")}/api/webhook`;
23+
const headers = { Authorization: `Bearer ${env.awarenessApiKey}` };
24+
const base = env.awarenessServiceUrl.replace(/\/$/, "");
25+
26+
try {
27+
const { data } = await axios.get<{
28+
subscriptions: Array<{ targetUrl: string }>;
29+
}>(`${base}/api/subscriptions`, { headers, timeout: 10000 });
30+
31+
if (data.subscriptions?.some((s) => s.targetUrl === targetUrl)) {
32+
console.log("[aaas] subscription already registered");
33+
return;
34+
}
35+
36+
await axios.post(
37+
`${base}/api/subscriptions`,
38+
{
39+
targetUrl,
40+
ontologyFilter: [USER_ONTOLOGY, PROFESSIONAL_PROFILE_ONTOLOGY],
41+
evaultFilter: [],
42+
},
43+
{ headers, timeout: 10000 },
44+
);
45+
console.log(`[aaas] subscription registered -> ${targetUrl}`);
46+
} catch (error) {
47+
const message = axios.isAxiosError(error)
48+
? (error.response?.data?.error ?? error.message)
49+
: (error as Error).message;
50+
console.error(
51+
"[aaas] subscription registration failed (continuing):",
52+
message,
53+
);
54+
}
55+
}

platforms/profile-editor/api/src/controllers/AuthController.ts

Lines changed: 0 additions & 134 deletions
This file was deleted.

platforms/profile-editor/api/src/controllers/DiscoveryController.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.

platforms/profile-editor/api/src/controllers/FileProxyController.ts

Lines changed: 0 additions & 69 deletions
This file was deleted.

0 commit comments

Comments
 (0)