From 0b50b14bdbaf93f9aaea76aaf7ec15822b2e34ae Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sun, 27 Sep 2026 00:31:04 -0700 Subject: [PATCH] docs(plans): name the membership predicate the server actually calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wren (74721): five lines in the connector plans state the server's rule in the present tense and name `isPodMember` — the creator-inclusive spelling, which is what those pages were written against and which no enforcement site calls any more. Retargeted to `isListedPodMember`, the predicate every gate in `routes/integrations.ts`, `installables.ts`, `podInvites.ts`, `activity.ts` and the bridges actually calls. - d8-phase-2-gate-surface.md:92 — a gate key must name a pod the owner is a member of - d8-phase-2-gate-surface.md:94 — the install verb, a gate key and `PATCH { podId }` all check it - connector-as-installable-app.md:346, :381, :385 — the write gate, the chosen pod, the target derivation Kept as history, per the ruling: connector-as-installable-app.md:224 (Vera, 2026-09-02, describing what the old gate did) and the AX-audit entry that records the two-functions-one-name collision. Not a safety fix and not sold as one: a stale identifier in prose fails loudly — a bare `require(...)()` throws, a destructured name is `undefined` and then throws — so nothing here was silently permissive. What was wrong is narrower and worth fixing: d8:94's "the list shows exactly what the server would accept" was false while the creator clause counted as membership, and the page now names the rule that makes it true. --- docs/plans/connector-as-installable-app.md | 6 +++--- docs/plans/d8-phase-2-gate-surface.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/plans/connector-as-installable-app.md b/docs/plans/connector-as-installable-app.md index 79d1289b0..672d534cf 100644 --- a/docs/plans/connector-as-installable-app.md +++ b/docs/plans/connector-as-installable-app.md @@ -343,7 +343,7 @@ one per user). The projected Integration row keeps today's pod binding: the page becomes the **first gate row**, and its pod is written to `Integration.podId` — the "active pod" of D12, honestly labelled as the single pod this connector relays until D8 fans out. Relay behaviour is byte-for-byte today's. The `Integration.podId` write on install is gated by -`isPodMember(pod, installer)` — the #1297 write gate, reused. +`isListedPodMember(pod, installer)` — the #1297 write gate, reused. **Phase 2 — D8's schema (separate PR, after this lands).** `Integration.scope: 'user'`, `podId` optional under a conditional validator, `config.gates[podId]`, and the outbound lookup @@ -378,11 +378,11 @@ plan leaves for the marketplace-unlock PR, and the `/browse` filter must admit ` - `linkedUserId` is stamped from the installer, after the relay default, never from the body. - Connect code is minted server-side (`mintConnectCode`); the body cannot supply one, and it is minted only by the final activation write — never by a projector (§2 step 6). -- The chosen pod is gated by `isPodMember` (write predicate, no admin read-bypass). +- The chosen pod is gated by `isListedPodMember` (write predicate, no admin read-bypass). - Install and uninstall both resolve their target from the caller's identity; neither accepts an installation id or a target from the body, so a caller can only ever act on their own row. - `grantedScopes` is descriptive, not enforced (Phase 1). Authorization is `auth` + - `isPodMember` + identity-derived targets, nothing else. + `isListedPodMember` + identity-derived targets, nothing else. - The install and uninstall verbs sit behind the integrations write limiter's shared key. - The Installable row carries no secret; H3's credential reference is the only future home. - Enable-time refusal of a group bind, the string-`'true'` coercion, and the attempt limiter diff --git a/docs/plans/d8-phase-2-gate-surface.md b/docs/plans/d8-phase-2-gate-surface.md index 58ec2b4bc..8af03f5f9 100644 --- a/docs/plans/d8-phase-2-gate-surface.md +++ b/docs/plans/d8-phase-2-gate-surface.md @@ -89,9 +89,9 @@ config.gates?: Record