Sense 25: The Pass — what you can do here, today, in this scope
Ce contenu n’est pas encore disponible dans votre langue.
Sense 25 · In bloom · Last touched 2026-08-20
- last_verified: 2026-05-25
Synced from
docs/design/sense_25_the_pass.mdin the engine repo — that’s the source; this page is a build-time mirror.
“Who am I right now, where am I right now, and what can I do here?”
A product-agnostic access model for the jazzisnow product family: jinflow, hrcentral, cuebook, and whatever comes next. Four levels (Identity → Roles → Passes → Capabilities), one five-level scope tree, three populations, one portable identity bus. Auth providers swap; the model doesn’t.
Status: proposed
Date: 2026-05-12 (initial framing); concept paper merged 2026-04-13 (e71b6252), extended 2026-04-26 (5166f2a4); revised 2026-05-13 for the three-category / Clerk-for-customers clarification + the Clerk-orgs-are-conditional second pass
Authors: the owner + Claude (March 2026 draft, April 2026 evolutions, May 2026 framing + two revision passes)
2026-05-13 revision notes (consolidated across both revision passes). This paper used to describe a “dual pool” architecture, a three-level scope tree, and an implicit “one customer = one Clerk org” mapping. All three framings were wrong. The current shape:
- Five-level scope tree: jazzisnow → customer → application → pack → tenant. The earlier three-level tree couldn’t represent multi-customer × multi-application × multi-pack × multi-tenant — the actual jazzisnow product portfolio.
- “Pool” vocabulary retired. What I previously called “pools” are just categories of access defined by where in the scope tree an identity binds. The same person can hold identities at multiple scopes — no separate pool concept needed.
- Three categories of access: jazzisnow-team (root scope), customer-admin (customer scope), tenant-end-user (tenant scope). Clerk is the auth provider for the customer category only. The earlier “jinflow pool” framing conflated jazzisnow team with paying customers.
- Clerk Orgs are conditional, not universal. A customer’s binding to Clerk depends on the customer’s shape: solo users get a Clerk User only (no org); B2B customers get a Clerk User + Clerk Org; federations get one Org with named sub-scopes. The earlier wording implied “one customer = one Clerk org always,” which would have been heavy and expensive for solo cases.
- Phase 1 work (1a–1d.2, shipped 2026-05-12) remains correct: contracts, validator, compiler, server query, and hydration hook are agnostic to access category. The vocabulary in
system/is naming-debt to clean up later (most likely →application/per-engine).
What pulled us in
Section titled “What pulled us in”JinDesk’s sidebar today is full of strings like cap: 'view:overview'. They’re scattered across Svelte files, jinflow-specific, and were written before anyone asked the question they’re now expected to answer.
Who am I right now, where am I right now, and what can I do here?
Three things are wrong with the current state:
- No scope.
'view:overview'makes sense in jinflow. In hrcentral, the question is whether the user can see this orgunit’s headcount, not whether they can see the overview page. The current strings don’t carry that information. - No category. A platform admin (jazzisnow team) and a tenant user (a CFO at one hospital) are both “users,” but they live in different worlds, get provisioned through different flows, and look at different surfaces.
- No migration path. Today’s strings are baked into Svelte files. There’s no way to grant a temporary pass, to compose two roles, or to ask “what would the CFO see?” without simulating their session by hand.
When hrcentral and cuebook arrive, they’ll need authorization too. If the engine code has to change for them, the design has failed.
This Sense is the model that absorbs the question once, in a place that survives every product.
The Cognitive Move
Section titled “The Cognitive Move”Four words look interchangeable: user, role, permission, scope. The cognitive move is that they aren’t. They’re four different concerns, each owned by a different actor, each evolving on a different cadence.
| Concern | Owned by | Cadence |
|---|---|---|
| Capability — one UI decision / API gate / data filter | Developer | Per code change |
| Pass — a coherent bundle of capabilities | Pack author | Per pack release |
| Role — a bundle of passes, named for a job function | Pack author / tenant admin | Per onboarding |
| Identity — a set of roles, scoped to where they apply | User (local) / admin (cloud) | Per session |
The relations are 1:n at every step. A role can include multiple passes; an identity can hold multiple roles. Roles are non-hierarchical — an engineer doesn’t inherit from an analyst. They’re separate role combinations. This avoids the fragile inheritance trees that RBAC systems collapse under.
Identity → Roles → Passes → Capabilities 1:n 1:n 1:nThe diagram is the spine of every section that follows.
The Four Capability Types
Section titled “The Four Capability Types”Capabilities are leaves. They’re atomic, typed, and answer one yes-or-no question (or, for two of the four types, return a value).
| Type | What it controls | Example |
|---|---|---|
ui_visibility | Show or hide an element | Sidebar entry, button, badge |
action | Enable or disable an interaction | ”Edit”, “Delete”, “Promote” |
api_gate | Server-side 403 | POST /api/signal/<id> |
dynamic_filter | Modifies the SQL query itself | CFO’s findings query returns only severity in ('high','medium') |
dynamic_filter is the hardest of the four to implement and the most powerful. It isn’t a hide — the row never reaches the user. A CFO with findings:dynamic_filter='high|medium' running a ?severity=low URL gets an empty result, because the underlying SQL adds the filter unconditionally. The UI doesn’t need to know.
The other three types are the bread of every BI tool. The fourth is what makes this an engine concern, not a frontend concern.
The Scope Tree
Section titled “The Scope Tree”Capabilities resolve in a five-level tree. Each level draws a real distinction; flattening any of them would conflate populations that should stay separate.
jazzisnow (singleton: the platform itself) │ └── customer (one paying organisation per node — the Clerk-org layer) │ └── application (jinflow / hrcentral / cuebook / …) │ └── pack (numetrix / interlogic / alptrack — within an application) │ └── tenant (rmc / inspire / rmc — within a pack)What each level means:
| Level | Examples | Who lives here |
|---|---|---|
jazzisnow | the platform | jazzisnow-team capabilities (cross-customer ops, billing oversight, new-customer provisioning) |
customer | ”RMC Group”, “VAI Foundation” | customer-admin capabilities — cross-application, cross-tenant for one paying org |
application | jinflow, hrcentral, cuebook | application-wide capabilities — e.g. view:findings is a jinflow-application capability that every jinflow pack inherits. hrcentral has its own application-level set. |
pack | numetrix, interlogic | domain-specific capabilities — e.g. material:edit_supply_org is a numetrix-pack capability. |
tenant | rmc, vai, inspire | identity grants for the end users of one deployment. |
A scope can also be a named list: tenants:[rmc, inspire] or packs:[numetrix, hrcentral]. This lets a customer admin grant access to “all hospitals in the EU” without listing each one.
Inheritance flows downward. A capability granted at customer applies to every application that customer runs; a capability granted at application:jinflow applies in every jinflow pack; a capability granted at pack:numetrix applies in every numetrix tenant. Most permissive value wins on conflicts.
The tree is what makes the model jazzisnow-wide, not application-specific. jinflow’s engine, hrcentral’s engine, and cuebook’s engine all read the same five-level tree. The engine code resolving a capability never knows which application it’s running in; it sees only “what does this principal hold at this scope.”
Note on Phase 1 directory layout. Today’s
system/directory in the jinflow engine repo is semantically the application scope for jinflow. When hrcentral lands, it ships its own application-scope artifacts the same way. Thesystemname is a naming-debt we’ll clean up when application scope becomes load-bearing (Phase 1d.5+).
Where Identities Bind in the Tree
Section titled “Where Identities Bind in the Tree”Three categories of access coexist. They are not three separate populations stored in three separate places — the same person can hold identities in multiple categories. What distinguishes them is which level of the scope tree their identity binds to:
| Category | Where the identity binds | Who lives here | Sees |
|---|---|---|---|
| jazzisnow-team | the root jazzisnow node | platform maintainers, customer-success engineers, on-call operators | every application, every customer, every tenant — operational scope |
| customer-admin | a customer node | the people who manage a paying customer relationship: billing contacts, IT admins on the customer side | their customer’s applications, packs, and tenants — the admin surface for their org |
| tenant-end-user | a tenant node | the people who use a deployed product day-to-day. The CFO at RMC; the HR officer at VAI | their tenant’s JinDesk; nothing else |
These aren’t disjoint pools. A jazzisnow employee who’s also a paying customer of their own product gets two identities at two different scopes. A consultant working for multiple customers gets multiple customer-admin identities. The four-level model (Identity → Roles → Passes → Capabilities) is identical at every scope; the scope tree carries the categorisation.
Where authentication providers fit
Section titled “Where authentication providers fit”The three categories don’t dictate three different auth providers, but in practice they tend to land on different ones:
- jazzisnow-team — internal directory (GitHub-identity-backed is the likely first move). Small population, internal-only.
- customer-admin — Clerk (see “Vendor Flexibility” for the conditional binding to Clerk Users / Orgs).
- tenant-end-user — the customer’s choice. Could be inherited from their Clerk org (via SSO), could be the customer’s own user pool, could be magic-link-only. We expose integration points; the provider is per-customer.
This is why Clerk is the customer-admin auth provider, not the everyone-everywhere login. The CFO of RMC doesn’t need a Clerk account to use JinDesk — their access is granted at the tenant scope, provisioned by RMC’s admin, authenticated by whatever surface RMC’s admin chose.
Why the categorisation matters
Section titled “Why the categorisation matters”- Onboarding: each category has its own provisioning path. Customer onboarding is a Clerk Org + admin grant. Tenant-end-user onboarding is the customer admin’s surface. jazzisnow-team onboarding is internal.
- Billing: customer-admin seats are typically billable per-Clerk-org. Tenant end-users aren’t a billing line item for us; they’re provisioned wholesale by the customer.
- Incident response: a Clerk outage doesn’t lock tenant end-users out of an already-authenticated session, because their capability resolution runs locally against the KLS. A jazzisnow-team outage doesn’t lock customers out either.
- Privacy: tenant end-user PII never sees Clerk. The customer can comply with data-residency rules without renegotiating with us about a third-party processor.
Local vs Cloud Mode
Section titled “Local vs Cloud Mode”The model has two operating modes, each with different defaults.
Local mode (jinflow explore on localhost):
- God-mode by default. The user owns the machine, owns the data, runs the binary. No authorization gates.
- Optional identity switcher. JinDesk can simulate any identity — “show me what the CFO would see, with low-severity findings filtered out.” This is for previewing, not for security.
- No network needed. The whole capability tree is resolved from the local KLS.
Cloud mode (deployed JinDesk):
- Admin-assigned, API-enforced. Every request carries a session; the API gate runs server-side.
- Identities managed externally (Clerk today for the customer-admin category; see next section).
- Capability resolution still local — the cloud’s KLS holds the same compiled tables as a local install. The auth provider answers “who is this person”; the KLS answers “what can they do here.”
The local default of god-mode is deliberate. Authorization is a defensive concern; defenders are absent at localhost. Forcing local users to manage permissions to access their own data inverts the model.
Storage — Compiled Into the KLS
Section titled “Storage — Compiled Into the KLS”YAML in the AFS → tables in the KLS. The compiler walks each pack’s capabilities/, passes/, roles/ directories, validates against the contracts, and bakes the tree into the per-tenant meta schema:
_{tenant}.capability_map -- every capability with its type + default_{tenant}.pass_definition -- every pass with its capability list_{tenant}.role_definition -- every role with its pass list_{tenant}.identity_grant -- per-principal grants (which roles in which scope)_{tenant}.principal -- the principal registry (see §12 of concept paper)These tables are read-only at runtime. JinDesk’s can() helper opens them, applies inheritance up the scope tree, and answers in microseconds.
This is what makes Sense 16 (P2P2P) possible. The proxy owner doesn’t need Clerk reachable to grant a CFO read-only access — the capability resolution happens against a KLS on their machine. The CFO logs in somehow (the auth provider’s problem) and the proxy enforces the rest.
Vendor Flexibility — Wrapping the Auth Provider
Section titled “Vendor Flexibility — Wrapping the Auth Provider”Clerk is the auth provider for the customer-admin category today. It is not in question for that category. But access models survive companies, and a paper that bakes Clerk into every layer would be a future-the owner tax we don’t want to pay.
Two scope clarifications before the techniques:
- Clerk is for the customer-admin category only. The jazzisnow-team category is internal — no customer-facing auth product needed. The tenant-end-user category is the customer’s call — their admin picks the surface; we provide the integration points.
- “Auth provider” in this section means a customer-admin provider. The five techniques below are about making Clerk swappable for that category. Tenant-end-user provisioning is a separate set of integration points, with its own pluggability story (sketched in Phase 4 of the migration path).
Clerk Users vs Clerk Orgs — a conditional binding
Section titled “Clerk Users vs Clerk Orgs — a conditional binding”Clerk has two primitives that matter for us: Users (individuals with credentials) and Orgs (groups of Users with shared admin tooling). They serve different shapes:
| Customer shape | Clerk binding | Notes |
|---|---|---|
| Solo / self-register | Clerk User only, no Org | Standard “consumer app” Clerk pattern. Stays on free-tier MAU. No org-pricing overhead. |
| B2B paying customer | Clerk User + Clerk Org | The standard B2B SaaS shape. Per-org pricing applies — but only for paying customers, by definition. |
| Enterprise with SAML | Clerk User + Clerk Org (Org-scoped SSO required) | SAML is configured per Org; without an Org we’d have to build our own SAML plumbing. |
| Parent with subsidiaries | parent Org + N child Orgs | Clerk supports Org hierarchy. Each sub-org is a customer-scope node. |
| Federation / consortium | one Org with named-list sub-scopes | Single Org, fan-out at the scope-tree level. One org cost. |
| Reseller (rare) | the reseller is the customer; their downstream clients are out-of-scope for us | We don’t try to authenticate the reseller’s customers. |
The customer scope in our tree is the conceptual level. The Clerk-binding is per-customer-shape. A solo user literally doesn’t have a Clerk Org — their User has identity grants at customer:solo_{user_id} (or simply at tenant:solo_default), bypassing the org layer.
This matters for cost: Clerk’s per-Org pricing kicks in only when we use Orgs, which is only for paying B2B customers. Solo / freemium users ride MAU pricing alone.
What Clerk Orgs buy us (when we use them)
Section titled “What Clerk Orgs buy us (when we use them)”The Org tier isn’t free, so the trade has to earn its keep. For B2B it does:
| Capability | What Clerk Org gives us | What building it ourselves would cost |
|---|---|---|
| Customer-admin self-service — invite/remove members, accept invitations, manage seats | Built-in UI + webhook events | Admin pages + invite-email flow + member CRUD + audit log |
| SSO / SAML per customer | Org-scoped SAML config; JIT provisioning out-of-the-box | Per-customer SAML ACS endpoint + JIT provisioning; this is real engineering |
| Per-org billing integration with Stripe | Clerk-Stripe per-seat counter wired into Org membership | Seat-counter + price-tier logic + invoice attribution |
| Active-organisation session context | Session carries an active_organization_id; users can switch contexts | Our own “currently acting as” primitive + session storage + switcher UI |
| Per-org audit + usage analytics | Activity dashboards per Org (logins, member changes, MAU) | Custom telemetry pipeline + dashboards |
The labour offload is the real reason to use Orgs for B2B. The Org isn’t a metadata store we’d need otherwise — our metadata lives in the KLS (per-principal grants, tenant scoping, capability resolution). Clerk Org replaces the operations infrastructure around member management, SSO, and billing.
One user, multiple Orgs
Section titled “One user, multiple Orgs”Clerk’s natural model handles this; ours maps cleanly.
Clerk: User: Alice (one user account, one set of credentials) Org memberships: - Alice ∈ Org "RMC Group" (Clerk role: admin) - Alice ∈ Org "VAI Foundation" (Clerk role: member)
Our KLS: Principal: prn_alice (one principal id; never duplicated) Identity grants: - prn_alice @ customer:rmc_group → identity 'customer_admin' - prn_alice @ tenant:rmc → identity 'analyst' - prn_alice @ tenant:vai → identity 'analyst'When Alice logs in, Clerk gives us her user_id + an active_organization_id. We look up prn_alice, then resolve identity grants for the active scope. Switching orgs via Clerk’s built-in switcher reloads with a new active_organization_id, and can() evaluates against grants scoped to that customer. Same principal, multiple memberships, one active context at a time.
The five vendor-flexibility techniques
Section titled “The five vendor-flexibility techniques”With that all clarified, the model’s vendor flexibility comes from five techniques, applied at the seams where Clerk meets our code:
1. The AuthProvider interface — abstract, not Clerk-shaped
Section titled “1. The AuthProvider interface — abstract, not Clerk-shaped”A small TypeScript / Python interface defines what we need from an auth provider:
interface AuthProvider { validateSession(token: string): Promise<SessionInfo | null>; listUsers(scope: ScopeRef): Promise<ProviderUser[]>; listOrgs(): Promise<ProviderOrg[]>; onUserCreated(handler: (user: ProviderUser) => void): void; onOrgMembershipChanged(handler: (event: MembershipEvent) => void): void;}Clerk implements this. Auth0, WorkOS, self-hosted Authentik could implement it without touching one line of engine code. The interface is ours; the implementation is the vendor’s.
2. The principal_id lives in our KLS, not in Clerk
Section titled “2. The principal_id lives in our KLS, not in Clerk”Every entity in the AFS that references a person carries a principal_id (prn_<random>), not a Clerk user_id. The mapping principal_id → provider_user_id lives in the _{tenant}.principal table:
principal_id provider provider_id emailprn_a8c1f... clerk user_2nKZf... alice@hospital.orgprn_2d4e8... github jazzisnow mig@…prn_99001... manual — (graffiti import)The provider column is what makes this portable. Migrating away from Clerk is an UPDATE principal SET provider='auth0', provider_id=... operation, not a rewrite. Existing references (signal authors, note authors, observation signers) keep working unchanged.
3. Capability resolution is local; sessions are remote
Section titled “3. Capability resolution is local; sessions are remote”The split between authentication (remote, vendor’s problem) and authorization (local, ours) is the firewall. Clerk validates “is this token still valid?” Our engine answers “what can this principal do here?” — by reading KLS tables that Clerk never sees.
A consequence: a Clerk outage doesn’t break JinDesk for already-authenticated sessions. The session token sits in a browser cookie; we read it, ask the local capability tables, and serve the page. Clerk only re-enters the flow at session expiry.
4. Webhook normalization at the boundary
Section titled “4. Webhook normalization at the boundary”Clerk emits org-membership webhooks in a Clerk-specific shape. We translate at intake into our own IdentityEvent shape (principal_id, scope, role_added, role_removed, timestamp). The rest of the engine consumes the normalized form.
When Auth0 / WorkOS / self-hosted replaces Clerk, only the webhook normalization layer rewrites. The downstream pipeline (IdentityEvent → identity_grant updates → KLS bake) is provider-agnostic.
5. Reasonable defaults, no provider-specific YAML
Section titled “5. Reasonable defaults, no provider-specific YAML”Pack authors write capabilities/explorer.yaml, not capabilities/explorer.clerk.yaml. The YAML never mentions Clerk. Defaults are expressed in our vocabulary (scope: tenant, default_pass: explore), and the auth provider is configured once at the system level, not per-pack.
If you read capabilities/*.yaml and can’t tell which vendor is providing auth, the design is right.
Reusability — The Load-Bearing Principle
Section titled “Reusability — The Load-Bearing Principle”The original concept paper opens with this (Section 0):
If the engine code needs to change for hrcentral, the design failed.
This is the test every section above has to pass. The four-level model, the five-level scope tree, the three access categories, the capability types, the storage layout — none of them depend on the word “hospital” or “material” or “signal”. Pack authors fill in those words. The engine just resolves the question.
When hrcentral defines its own capabilities — orgunit:view_headcount, person:edit, qualification:assign — they slot into the same compiler, the same KLS tables, the same can() helper. The Sense 27 Lens-browser idiom already crossed this bridge for entity-agnostic chart panels; this Sense does it for access control.
Cuebook will land with its own vocabulary. The shape of the model accommodates it. That’s the win.
Artifact Ownership — Names Become Principals
Section titled “Artifact Ownership — Names Become Principals”Section 12 of the concept paper (added 2026-04-26) extends the model with a parallel concern: every field in the AFS that names a person, role, or group should reference a principal_id, not a free-text string.
Today’s provider: "an SME @ the source vendor" and delivered_by: "the ward pharmacist" are graffiti. Useful, attributable, but not structured. Phase 1.5 of the migration plan introduces the principal registry and a translation pass: every reference becomes a principal_id with a fallback display string for legacy data.
This is parallel to authorization, not part of it. But the same model — _{tenant}.principal, the provider-portable mapping, the prn_<random> shape — serves both concerns. Authentication, authorization, and attribution all read from the same registry.
Migration Path
Section titled “Migration Path”Phased, smallest-first. Each phase has a clear access category so the work stays scoped:
| Phase | What | Category | Status |
|---|---|---|---|
| 0 | Define the model (this Sense + the concept paper) | — | ✅ done |
| 1 | Local-mode identity switcher: YAML compiler + can() helper + sidebar filtering | tenant-end-user (god-mode + previewing) | shipping (1a–1d.2 done) |
| 1.5 | Principal registry + artifact-ownership migration (§12 of concept paper) | — | pending |
| 2 | API enforcement middleware + 403s | tenant-end-user | pending |
| 3 | Clerk integration for the customer-admin category — Clerk Users (solo) + Clerk Orgs (B2B), customer admin UI, principal lookup | customer-admin | pending |
| 4 | Tenant-end-user provisioning surface — the customer admin’s tool for granting roles to their CFO / analyst / auditor. Vendor is the customer’s call (SSO, magic links, etc.); we expose integration points. | tenant-end-user | pending |
| 5 | Scope tree expansion: customer + application levels become load-bearing in the compiler + KLS | — | pending |
| 6 | Dynamic filter query rewriting | tenant-end-user | pending |
| 7 | jazzisnow-team admin surface — internal tool for cross-customer ops | jazzisnow-team | pending |
Phase 1 is purely local. No Clerk, no cloud, no network. The compiler ingests YAML, the can() helper resolves capabilities, JinDesk’s sidebar respects them. A user can simulate “what the CFO would see” by switching identity in a dropdown.
This sequencing keeps each phase shippable on its own. Phase 1 alone makes the local JinDesk a richer demo (Sense 24’s Steward gets visible). Phase 2 closes the cloud loop without depending on Clerk. Phase 3 is where Clerk lands — but only for the customer-admin category, with the Users-vs-Orgs binding determined per customer shape. Phase 4 is the tenant-end-user provisioning surface; the vendor for that category is the customer’s call, and we expose integration points rather than mandating a provider.
How this manifests in jinflow
Section titled “How this manifests in jinflow”Identity & Passes runs on Clerk for the customer-admin layer, with dev/prod environment separation (Sense 48 The Stage — folded into deployment workflow). Every JinDesk write happens as a named Principal whose Pass attributes attach to the commit via the Scribe. JinDesk’s chrome carries the env indicator pill so you can never confuse dev and prod sessions, and the role/pass model gates Atelier capabilities per-Principal.
- In the app: Passes (your active passes for this tenant) · Principals (everyone with access) · Who (the per-tenant access registry)
- CLI:
jin login(env-aware Clerk auth) ·jin invite(issue a Pass) ·jin sync-principals(reconcile the AFS-side registry) ·jin revoke(terminate a Pass)
Status: shipped through Phase 3 (Clerk-backed sign-in, dev/prod planes, dual-pool routing, invite + revoke surfaces, Scribe attribution per write). Phase 4 (tenant-end-user provisioning surface) is forming.
Open Questions
Section titled “Open Questions”The concept paper’s §16 lists seven, six still open after the 2026-04-26 update:
- Anonymous access policy. What does a public-facing tenant page show to a user with no session?
- Cross-scope conflict semantics. A pack-level capability granted, a tenant-level deny — who wins? (Most-permissive is the default; is there a scope where deny-wins is correct?)
- Clerk pricing tier for paying customers. Which Clerk plan supports the Org count we’ll grow into? Now sharpened: solo / free-tier users sit on MAU pricing (Clerk Users only, no Orgs); Org pricing applies only when a customer pays for B2B features. The orders of magnitude are much smaller than the original “every customer is an Org” framing implied.
- Dynamic filter composition. Two roles each add a
findings.severityfilter — what’s the composition rule? Union, intersection, last-wins? - Temporary grant notifications. When an admin grants a 7-day pass, should the recipient be notified, and through what channel?
- Multilingual
display_namefor users vs roles. Roles need translation (acforole displays asFinanzchefin German). Users probably don’t (Alice is Alice). Where’s the line? - Email storage location. PII in the KLS vs. PII at the auth provider — which fields live where, and how do they sync? Now sharpened by the three-category framing: tenant-end-user PII probably stays out of Clerk entirely.
- Tenant-end-user provisioning surface (Phase 4). What’s the minimal customer-admin tool that lets a customer wire SSO / magic links / their own user store to a tenant deployment? Is this a YAML hook, an admin page, or a separate provisioning API?
- jazzisnow-team admin surface (Phase 7). Where do the platform maintainers’ identities live? GitHub-backed, separate Clerk instance, or internal directory? This was implicit in the older framings; the three-category model makes it explicit.
Phase 1 doesn’t depend on resolving any of these. Phases 3, 4, and 7 each depend on a different subset.
Related Senses
Section titled “Related Senses”- Sense 16 — P2P2P. The three-category framing and offline-first capability storage are what make P2P2P actually private. The proxy owner’s machine resolves tenant-end-user capabilities locally; no Clerk call per request, so no session metadata leaks to the cloud. Tenant-end-user sovereignty is the natural consequence — the customer can keep their end-users entirely out of Clerk if they choose.
- Sense 24 — The Steward. The Steward is the third native habitat (analyst, CFO, steward). They run different commands, see different surfaces — the Pass model lets us encode that without forking the codebase.
- Sense 28 — The Direct Line. Cloud signs SQL, never sees rows. Capability resolution is the missing piece: who’s allowed to sign which SQL? The capability tree decides.
Full Specification
Section titled “Full Specification”This Sense is the framing. The full mechanical detail — every YAML schema, every storage table column, every resolution algorithm, every edge case — lives in:
docs/design/sense_25_identity_and_passes.md (1,065 lines)
- §0 Reusability principle
- §1 Vocabulary
- §2 Four-level model
- §3 Capability types
- §4 Scope tree
- §5 Capability resolution
- §6 Identity lifecycle
- §7 Local vs cloud
- §8 Dual pool
- §9 Resolution chain
- §10 Storage
- §11 Coexistence (GitHub OAuth, provider-agnostic patterns)
- §12 Artifact ownership and assignment
- §13 Default vocabulary (jinflow pack)
- §14 Admin UI
- §15 Migration path
- §16 Open questions
- Appendix A — Comparison with the March 2026 draft
When implementing Phase 1, read the concept paper. When reasoning about whether a new product fits the model, this Sense is enough.
Heads-up on the concept paper. The concept paper currently uses the older vocabulary: “dual pool” instead of three categories, three-level scope tree instead of five, and “one customer = one Clerk Org” instead of the conditional Users-vs-Orgs binding. The 2026-05-13 revisions on this Sense haven’t been propagated into the concept paper yet — pending a focused pass that updates §4 (scope tree), §8 (pool → category), §11 (coexistence), and §15 (migration path). Until that lands, this Sense is the authoritative current framing; the concept paper is authoritative for everything that didn’t change (YAML schemas, storage layout, resolution algorithm).
Numerical neighbors: ← Sense 25 — Identity, Roles, Passes, Capabilities — Concept Paper · Sense 26: The Workshop — the pack ships its own design →