DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path scoping-notes/loomworks-ova-reach-enforcement-scoping-note-v0_1.html

Loomworks — OVA reach enforcement — scoping note — v0.1

Version. 0.1
Date. 2026-07-28
Status. Scoping note. Consumes the Step 0 evidence; presents the resolution of the arc's central question and the slice structure; surfaces three Operator decisions. Does not draft a change request — that follows this note per the standing two-step.
Author. Claude.ai. Operator: Marvin Percival.
Grounding. loomworks-ova-reach-enforcement-step-0-report-v0_1 (engine 1aac815, zero drift from the venture-diligence inspection — the two reports describe an identical tree); loomworks-vertical-vc-diligence-cc-inspection-report-v0_1 V1; canonical seed v0.12 (Memory section, reach and contribution axes); loomworks-foray-ova-integration-strategy-investigation-v0_1 (Option E, seam-and-stub); loomworks-ova-reach-enforcement-scoping-handoff-v0_1 (parent).

Plain-language summary

What this note settles. The arc opened on the question: can reach be withheld below membership? The evidence answers it by inversion. The engine's one universal predicate — membership existence, which all sixty-three engagement-scoped reads converge on with no bypass — is not the obstacle. It is the enforcement mechanism, already built, already holding. The build is not a read-side rework; it is a contribution pathway for people who are never members. An external contributor who is not a member is excluded from every read by the predicate that already exists, and their contribution stays fully attributed because attribution never touches membership.

What the build is. A credentialed contribute-only pathway for non-members, authorized through a generalization of the authorizer stub already in the codebase — which makes this the OVA contract's first real question, landing behind the seam the integration strategy already commits to. Zero read-side changes in the first slice.

What decisions are needed. Three, stated in Section 7: confirm the candidate selection; decide how the seed absorbs two findings (the held-gate extension to engagements, and the "seam is in place" sentence that V1 found to be posture); and set the first slice's boundary.


1. The central question, resolved by inversion

The handoff posed: can a reach access-control list exclude an engagement's own contributor from reading the engagement they contribute to? It weighed three candidates — a reach ACL below membership (A), a participation shape that is not membership (B), and a hybrid ratifying membership-implies-reach with non-members contributing through a gate (C) — and asked whether the smallest build, C, quietly under-delivers.

The evidence says C does not under-deliver. It delivers exactly, because of two findings that compose:

Attribution is membership-free (V5, HOLDS). Attribution is an embedded actor-reference value object with a snapshotted display name; memory_events carries exactly one foreign key — to the engagement — and no attribution path anywhere targets memberships. A non-member's contribution is fully attributed, fully provenanced, and fully renderable. Only access differs.

The read surface has one predicate and no bypass (V2). All sixty-three engagement-scoped reads converge on membership existence. CC found no read that skips it. So for a person who holds no membership, exclusion from every read is not a feature to build — it is the current behavior of the current predicate.

The composition: an external contributor who contributes without ever becoming a member gets contribute-without-read from the substrate as it stands. The two-rung ladder the venture-diligence inspection found — membership grants read, designations grant write — was read there as the blocker. It is the fence. What is missing is not a way to keep non-members out of reads; it is a way to let non-members in to contribution.

The handoff's caution about C — that it might quietly under-deliver the two commercial motions — is answered directly. The deal vertical's shape is: founder, reference, interviewee contribute; deal team reads. Under C the externals are never members; the fence handles reads. The Appendix A motion's shape is: target's people contribute; investor reads. Same shape — the investor side holds the memberships, the target's people are credentialed non-member contributors. Both motions are served, and candidate A's resolver-layer rework — a read-authority concept on the resolved actor, a subtractive designation the additive model has no shape for, and a permission-check pass over sixty-three routes across three enforcement paths — buys neither motion anything the fence does not already provide.

Resolution: candidate C, renamed for what it is — contribution authorization for non-members. Candidate A is not rejected as wrong; it is deferred as the restricted-scope enforcement the seed's reach axis will eventually need for member and cross-engagement restriction (Section 5), which is a different question with a different consumer.

2. The admission gate arrives free

V3 returned BREAKS on held-as-admission: the data-layer commit check verifies only that the actor is not an agent and the state is held — it never compares committer to contributor, so a member with the contributor designation drafts and admits their own contribution in one session. "Trusted core" appears nowhere in any authorization sense. The held state today is a save-before-submit cycle reusing the seed's word.

For members, this note treats that as accepted semantics, not a defect: a trusted-core member writing directly into Memory is precisely what the seed's contribution axis says trusted cores do. The seed's gate is for outside contributions — and under candidate C, the gate assembles itself from existing parts: a non-member's contribution enters held; the commit transition sits behind the membership predicate plus the commit designation; a non-member therefore structurally cannot reach the admission step. Held-until-admitted-by-the-trusted-core, with the deal team as the de-facto trusted core, falls out of the composition with no new admission logic. The self-admission looseness among members remains, and is named as a residue for the future shared-scope (domain) work where trusted-core-proper — vetted-writer sets with scope-level admission practice — is the real subject.

3. The authorizer — generalize the stub, per Option E

V4 found two seams. The Phase 45 verify_companion_authorization seam is genuine but its signature fixes the question to delegation — no parameter for a reader or contributor distinct from the delegator. The right ancestor is _alpha_authorizer_stub (credit/cross_engagement_memory.py:65-85): (requesting_person, requesting_engagement, target_engagement) → bool, gating a cross-engagement read, deny path already written — right shape, wrong scope, one hardcoded target, module-private, unconditionally true.

The build generalizes it into the Option E authorizer the integration strategy recommends: authorize(actor, action, resource, context) → decision, module-public, with the non-member contribution question as its first real caller and the existing stub's caller migrated onto it. This is deliberate sequencing, not convenience: the integration strategy's whole argument is that Loomworks's authorization needs should drive the OVA contract's hardening, and "may this outside person contribute into this engagement under this credential" is a better first question for that contract than any read question — it exercises credential issuance, scoping to a single engagement and action, expiry, and revocation, which are the capability semantics OVA-proper will answer. The reach questions join the same contract at Slice 3.

The credential's concrete form (a scoped invitation token the deal team issues to the founder; its delivery surface; its lifetime and revocation) is change-request-level design, bounded by one rule from the standing architecture: the authorizer check fires at the substrate on the contribution write path — the same chokepoint discipline as FORAY — never only at the surface that renders the contribution form.

4. What Slice 1 is, sized against the evidence

Slice 1 — non-member contribution pathway. The authorizer generalization (Section 3); a credentialed contribution entry point for non-members writing held assertions with embedded actor-reference attribution (V5 confirms nothing downstream breaks); the credential issuance surface for the Operator; FORAY anchoring on the new write path per standard event conventions; and the external contributor's own-submission surface (they see what they submitted, nothing else — a new narrow read that takes the credential, not the membership predicate). Zero changes to the sixty-three existing reads. No migration is obviously required beyond whatever the credential store needs — the change request's Step 0 confirms. Sized: a small-to-medium change request, one arc, no sub-phases.

What Slice 1 explicitly does not do: no access-mode column, no ACL, no read-side authorizer consultation, no middleware. Those are Slices 2 and 3.

5. Slices 2 and 3 — the deferred reach work, recorded now

Slice 2 — the declaration. V1 returned BREAKS on the declared seam: no access-mode, ACL, or reach element exists anywhere in schema or migrations; the only structural hit, visibility, is a false friend by its own migration's documentation ("Schema-only — no behavior in Phase 14"), read at exactly two dashboard lines to exclude personal engagements, with the promised value set never completed. Seed v0.12's "the access mode is declared and the seam is in place" is posture. Slice 2 makes the sentence true: an access-mode declaration on the engagement (default open), an ACL structure behind the authorizer contract, still unenforced on reads. Small, mostly schema.

Slice 3 — reach enforcement proper. Restriction of members and cross-engagement reach to restricted scopes — the seed's reach axis in full, the piece candidate A pointed at. CC's closing caution governs its design: there is no auth middleware (the one docstring reference to "contributor middleware" is stale), and enforcement today runs through three separate paths — the resolver dependencies, in-body verify_project_membership, and the dashboard SQL CTEs. A reach check added at the resolver layer alone would silently miss the seven orchestration routes, which is where the partner-facing reads live. Slice 3 therefore consolidates the read predicate into a single authorizer consultation reached by all three paths before enforcing anything through it — the chokepoint must exist before the guarantee routes through it. Slice 3 has no current consumer pressing on it; it waits for the domain layer or a restricted-engagement need, with this paragraph as its standing design constraint.

V6, engagement-first. The report's scope inventory supports enforcement landing engagement-first; the authorizer contract is written scope-shaped — resource is a scope reference of which an engagement is the present kind — so the wider scopes the seed's N-scope model names slot into the same contract when the domain layer arrives, rather than forcing a second contract.

6. What this arc unblocks, precisely

The deal vertical's isolation claim converts from committed-direction to demonstrable at Slice 1, not Slice 3 — the vertical's externals are non-members, and the fence already holds. Deal walkthrough v0.4 and deal seed v0.3 trigger on Slice 1's change request landing, not on full reach enforcement. The Appendix A investigation is unblocked for drafting now: the enforcement shape it needed to cite exists as this note's Sections 1–4. The fund record vertical was never blocked.

7. Operator decisions

D1 — Candidate selection. Confirm candidate C as resolved in Section 1: contribution authorization for non-members now; candidate A's read-side rework deferred to Slice 3 with a design constraint recorded. Recommendation: confirm.

D2 — How the seed absorbs two findings. First: candidate C extends the held-until-admitted gate — which seed v0.12 describes for shared scopes — down to engagements for outside contributions. The seed's trust-graph language is arguably scope-general already, but the extension deserves a sentence rather than an inference. Second: the "seam is in place" sentence is factually posture until Slice 2 lands. Options: (a) fold both into the queued seed v0.13 (which already carries the provenance-threads candidate) as riders; (b) a standalone v0.13 amendment now, provenance-threads becoming v0.14; (c) leave the seed until Slice 2 makes the sentence true and amend once. Recommendation: (a) — one amendment event, and neither finding is urgent enough to jump the queue.

D3 — Slice 1 boundary. Include Slice 2's declaration in Slice 1's change request, or hold Slice 1 to the contribution pathway alone. Recommendation: hold Slice 1 to the pathway alone — the declaration has no behavior until Slice 3 and folding it in couples an unpressured schema change to a pressured build.

On D1–D3 confirmation, the next artifact is the Slice 1 change request drafting handoff, standard two-step, with its own Step 0 pre-flight verifying the contribution write path, the stub's caller, and the credential-store shape against live code at drafting time.


DUNIN7 — Done In Seven LLC — Miami, Florida
Loomworks — OVA reach enforcement — scoping note — v0.1 — 2026-07-28