chain-selective-access

Chain · Selective access — who may see what, frozen at issue

Parent: requirements-to-design

Status: DEEPEST CHAIN — design finalized, heaviest tests.

L0 · Vision

introduction — modes are roles: four apps sharing one corpus; ACL is the hard wall on what's reachable, role is the soft framing on what gets surfaced. boundaries — a "thought-leadership filter for selective engagement", not open broadcast, not anyone-can-book. design-principles — "serve those who already love it; keep some access friction".

L1 · Promise

The owner decides, per audience, which slice exists at all; a visitor's rules are fixed the moment their invitation is issued and can only ever be narrowed, never widened.

L2 · Requirements (journeys & features)

The owner code-management journeys and the visitor gate journeys (entry: Code / BYOAI / Request access), plus quota; admin surfaces Codes + Access Requests; the gate page /gate.

L3 · Design decisions

The finalized three-layer design (capability-acl-hierarchy, decisions locked 2026-06-23): pure-AND narrowing global(live) ∧ role(frozen) ∧ ¬code-deny(frozen) (acl-and-quota-granularity); tri-state overrides KILLED, sparse deny tables (a code can only subtract); freeze/live asymmetry (role-snapshot-frozen); AccessCode = invitation, ONE table, no parallel concept; identity via neutral _meta (trusted-identity-via-meta); BYOAI containment (byoai-envelope, byoai-browser-vault).

L4 · Engineering artifacts

Tables access_codes (assumed_role_id, prompt_id / inline_prompt, slug, microsite_id, limit_per_period), code_capability_denials, code_skill_denials, code_corpus_denials, code_members, capability_settings, roles/role_skills/role_mcp_servers/role_corpus_uris, embeds (code_id UNIQUE, key_id / public_key); backend/internal/conversation/usecase/visitor_role_snapshot.go; RoleSnapshot.deniedCapabilities for ACL=always caps; the quota system.

L5 · Verification

The heaviest e2e estate in the repo: acl-capability-matrix, acl-skill-matrix, acl-freeze-isolation, visitor-chat-permissions-deny, gate-access — plus the timing story (ACL at session establishment via ErrHidden; only monitor+secret-scan at call-time).

Status & gaps

Global layer landed; role/code deny per finalized design; corpus-glob ACL now LANDED (AllowsCorpusEntry enforced on every read; raw://** hard-denied; per-code corpus narrowing via code_corpus_denials, 2026-07-16 6395374b0); per-code prompt LANDED (access_codes.prompt_id or inline_promptcodePromptBody frozen into the snapshot, layered after the role persona in visitor_chat_prompt.go). Since the 2026-08-30 sweep: system-derived codes carry a 64-bit random suffix instead of 16 (2026-09-01 1ca9d9564, access/entity/code_derive.go, driven by a pentest); a code exposed on a third-party site goes through embed-credential-never-carries-the-code (2026-09-01 2098975db); each code owns a landing path /c/<slug> (2026-09-06 4e383c2a7 + c6c54ce88, DeriveSlug, migration 2026-09-06-access-code-slug.sql); the code string can be rotated for leak recovery, codes.rotateRotateCode purging the code's sessions (2026-09-07 505b3fc4f + 6ed1759bb, access/usecase/codes.go:113); a new code on the visitor page switches the session and an invalid one lands on /gate (2026-09-06 230a17025).

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →