@assembly-js/app-foundation 0.0.8-rc.0 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -10,6 +10,10 @@ In user-facing chat, never mention ASSEMBLY_ENV, COPILOT_ENV, or any other inter
10
10
 
11
11
  **If an SDK auth warning appears mid-build** — for example, a "You must set ASSEMBLY_ENV=local" message from the SDK initializer — treat it as expected transient state. The sandbox resolves it automatically as the build progresses. Do not surface this message in chat and do not ask the user to set any environment variables.
12
12
 
13
+ When you describe a feature or a change, describe what the user and their clients will **experience** — who can open the app, what each audience sees or can do. The mechanics that produce it are plumbing too: keep manifest keys (`surfaces`, `app.json`), file names, SDK method names, and identity fields like `clientId`/`internalUserId` out of chat unless the user asks how it works. "Clients will see only their own record" is something they can act on; "add a client surface to the manifest and branch on `identity.clientId`" is not.
14
+
15
+ When a request implies a scope or permission change, apply it and report the product effect — don't stop to ask the user to approve the mechanics. "When a client views this, show them their own info" already means "make this client-facing," so make the change and say what happened ("clients now see just their own record; your team still sees everyone"). Ask first only on a genuine product choice the user can weigh — who should see the app, what each audience sees — phrased in those terms, never as a manifest or surface decision.
16
+
13
17
  ---
14
18
 
15
19
  ## Skills
@@ -21,6 +25,9 @@ Assembly-specific gotchas live in `.claude/skills/<name>/SKILL.md`. Invoke them
21
25
  - `assembly-companies` — many-to-many with clients; placeholder companies (excluded from `listCompanies` by default for these apps)
22
26
  - `assembly-clients-companies` — REQUIRED when the app stores or scopes data by client or company: scoped tables carry BOTH a `clientId` and a `companyId` column and are filtered on the intersection (never one dimension); a client viewer always has an active `companyId`; `companyIds[]` builds pickers only and `client.companyId` is deprecated
23
27
  - `assembly-custom-fields` — workspace-defined fields, multiSelect rules
28
+ <!-- feature:platform-mcp -->
29
+ - `assembly-platform-mcp` — provisioning workspace configuration at build time via the scoped `mcp__platform__` tools: create a custom field the app depends on instead of shipping an app that gates on missing workspace setup. Workspace configuration only — never client-facing data.
30
+ <!-- /feature:platform-mcp -->
24
31
  - `assembly-native-resources` — native message channels, forms, portal files/file channels: never hardcode their IDs, discover them at runtime
25
32
  - `assembly-mutations` — minimal `requestBody` rule for `update*` calls
26
33
  <!-- !feature:notification-settings -->
package/dist/client.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './session-exchange.js';
2
2
  export * from './network-capture.js';
3
+ export * from './parent-origin.js';
3
4
  export * from './client-companies.js';
4
5
  export * from './pagination.js';
5
6
  export * from './theme.js';
package/dist/client.js CHANGED
@@ -7,6 +7,9 @@
7
7
  // also runs in the Edge middleware runtime that proxy.ts uses.
8
8
  export * from './session-exchange.js';
9
9
  export * from './network-capture.js';
10
+ // Self-running on client module load (see the module comment): registers the
11
+ // framing origin with the app-bridge allowlist so custom-domain portals work.
12
+ export * from './parent-origin.js';
10
13
  export * from './client-companies.js';
11
14
  export * from './pagination.js';
12
15
  export * from './theme.js';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Resolve the origin of the window framing this app.
3
+ *
4
+ * Prefers `location.ancestorOrigins` (browser-attested, immune to referrer
5
+ * policy; Chromium/WebKit) and falls back to `document.referrer` (Firefox).
6
+ * Returns null outside an iframe or when neither source is available —
7
+ * e.g. a restrictive Referrer-Policy on the parent in Firefox.
8
+ */
9
+ export declare function resolveParentOrigin(): string | null;
10
+ /**
11
+ * Add the framing origin to the bridge's postMessage allowlist.
12
+ *
13
+ * Idempotent (the bridge holds origins in a Set) and restricted to https
14
+ * parents — local development origins are already on the default allowlist,
15
+ * so an http parent never needs registering.
16
+ */
17
+ export declare function registerParentOriginWithBridge(): void;
@@ -0,0 +1,57 @@
1
+ // Registers the app's real framing origin with the app-bridge postMessage
2
+ // allowlist, so the bridge works on workspaces with custom portal domains.
3
+ //
4
+ // The bridge SDK ships a hardcoded origin allowlist (localhost + assembly
5
+ // domains) and silently drops every outgoing and incoming message when the
6
+ // parent origin isn't on it. On a custom-domain portal that kills header CTAs,
7
+ // session-token refresh, and theme sync. Trusting the framing origin here is
8
+ // sound because the proxy already gates who may frame the app at all: its CSP
9
+ // frame-ancestors directive allows only the static assembly domains plus this
10
+ // workspace's own portal URL, and the browser enforces that before any of this
11
+ // bundle runs. Inside the frame, the browser-reported parent origin is
12
+ // therefore always one the platform trusts.
13
+ import { AssemblyBridge } from '@assembly-js/app-bridge';
14
+ /**
15
+ * Resolve the origin of the window framing this app.
16
+ *
17
+ * Prefers `location.ancestorOrigins` (browser-attested, immune to referrer
18
+ * policy; Chromium/WebKit) and falls back to `document.referrer` (Firefox).
19
+ * Returns null outside an iframe or when neither source is available —
20
+ * e.g. a restrictive Referrer-Policy on the parent in Firefox.
21
+ */
22
+ export function resolveParentOrigin() {
23
+ if (typeof window === 'undefined')
24
+ return null;
25
+ if (window.parent === window)
26
+ return null;
27
+ const ancestor = window.location.ancestorOrigins?.[0];
28
+ if (ancestor)
29
+ return ancestor;
30
+ try {
31
+ const referrer = document.referrer;
32
+ if (referrer)
33
+ return new URL(referrer).origin;
34
+ }
35
+ catch {
36
+ // Unparseable referrer — fall through to null.
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Add the framing origin to the bridge's postMessage allowlist.
42
+ *
43
+ * Idempotent (the bridge holds origins in a Set) and restricted to https
44
+ * parents — local development origins are already on the default allowlist,
45
+ * so an http parent never needs registering.
46
+ */
47
+ export function registerParentOriginWithBridge() {
48
+ const origin = resolveParentOrigin();
49
+ if (!origin || !origin.startsWith('https://'))
50
+ return;
51
+ AssemblyBridge.configure({ additionalOrigins: [origin] });
52
+ }
53
+ // Run on module load: every app's client bundle imports this package (authFetch,
54
+ // network capture), and module evaluation precedes hydration — so the origin is
55
+ // registered before any component's first header/session-token call. Baked app
56
+ // files never call this module directly, which is exactly why it self-runs.
57
+ registerParentOriginWithBridge();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assembly-js/app-foundation",
3
- "version": "0.0.8-rc.0",
3
+ "version": "0.0.9",
4
4
  "description": "Versioned foundation helpers and build context for Assembly generated apps",
5
5
  "type": "module",
6
6
  "files": [
@@ -84,22 +84,3 @@ Send the structured object — a bare string is accepted for backwards compatibi
84
84
  - **Clearing a value**: empty array `[]`, not `null` or `undefined`.
85
85
  - **Either `key` or `id` works** as the inner option value — use `key` by convention.
86
86
  - Same shape applies to `createClient`, `createCompany`, `updateCompany`.
87
-
88
- <!-- feature:platform-mcp -->
89
- ## Provisioning fields at build time (platform MCP)
90
-
91
- You have a scoped platform MCP server (tool prefix `mcp__platform__`). When the app you are building depends on a custom field the workspace does not have yet — the user asked for "call clients at their phone number" and no Phone-type client field exists — provision it yourself at build time instead of shipping an app that gates on missing workspace config:
92
-
93
- ```
94
- mcp__platform__custom_fields with action "list" — check what exists first
95
- mcp__platform__custom_fields with action "create" — create the missing field
96
- ```
97
-
98
- Rules:
99
-
100
- - **Check before creating** (`list`, match case-insensitively by name) — never create a duplicate of a field that already exists under a slightly different name.
101
- - **Creating a field does not replace graceful handling.** The app's runtime code must still handle the field being absent or renamed later (discover by name, render a setup hint) — you provision the field the app *starts* with; you don't get to assume it forever.
102
- - **Never delete fields.** Deletion is not available to you by policy: fields carry data on real client records.
103
- - **This tool is for workspace configuration only.** Do not reach for `mcp__platform__*` to create clients, send messages/notifications/invoices, or touch any client-facing data — those denials are enforced server-side and the attempt wastes a turn.
104
- - Tell the user in chat, in product terms, when you create a field ("I added a Phone number field to your client records so the app can call them").
105
- <!-- /feature:platform-mcp -->
@@ -0,0 +1,23 @@
1
+ <!-- feature:platform-mcp -->
2
+ ---
3
+ name: assembly-platform-mcp
4
+ description: Use when the app you are building depends on workspace configuration that does not exist yet — most commonly a custom field on clients or companies (the user asked for "call clients at their phone number" and no Phone-type client field exists). You have a scoped platform MCP server (tool prefix mcp__platform__) for provisioning that configuration at build time instead of shipping an app that gates on missing workspace setup. Workspace configuration only — never client-facing data (no creating clients, sending messages, notifications, or invoices).
5
+ ---
6
+
7
+ ## Provisioning custom fields at build time
8
+
9
+ You have a scoped platform MCP server (tool prefix `mcp__platform__`). When the app you are building depends on a custom field the workspace does not have yet — the user asked for "call clients at their phone number" and no Phone-type client field exists — provision it yourself at build time instead of shipping an app that gates on missing workspace config:
10
+
11
+ ```
12
+ mcp__platform__custom_fields with action "list" — check what exists first
13
+ mcp__platform__custom_fields with action "create" — create the missing field
14
+ ```
15
+
16
+ Rules:
17
+
18
+ - **Check before creating** (`list`, match case-insensitively by name) — never create a duplicate of a field that already exists under a slightly different name.
19
+ - **Creating a field does not replace graceful handling.** The app's runtime code must still handle the field being absent or renamed later (discover by name, render a setup hint — see the assembly-custom-fields skill for the runtime contract) — you provision the field the app *starts* with; you don't get to assume it forever.
20
+ - **Never delete fields.** Deletion is not available to you by policy: fields carry data on real client records.
21
+ - **This tool is for workspace configuration only.** Do not reach for `mcp__platform__*` to create clients, send messages/notifications/invoices, or touch any client-facing data — those denials are enforced server-side and the attempt wastes a turn.
22
+ - Tell the user in chat, in product terms, when you create a field ("I added a Phone number field to your client records so the app can call them").
23
+ <!-- /feature:platform-mcp -->