# K1 access projection
`kcode-k1-access-projection` owns the synchronous derived authorization and discovery projections for the logical KTO subsystem `k1-access-subsystem`. Its caller supplies one projection root and KTO ordering. It performs no registration, Groups lookup, authentication, network work, retry, timeout, worker, or authorization beyond its documented Access checks.
## API
`ApplyOutcome` is `Applied(AccessRevision)`, `Unchanged(AccessRevision)`, or `Rejected(String)`. The crate reexports the Access action, witness, identities, authorization inputs and results, targets, transaction ID, subsystem ID, and ordering type used by its public API.
`Projection::open(root, ordering)` opens both derived stores. It accepts a nonempty snapshot only when the Access cursor equals the discovery checkpoint, every current normalized user or group owner/viewer has that object's ID in discovery, and the complete Access snapshot validates against canonical KTO actions. Any ordinary invalidity or cursor mismatch clears both derived stores and returns an empty projection for Ordering replay at genesis. KTO query failure is returned without clearing.
`apply(callback_txid, action)` serializes a callback. Every callback, including rejected, unchanged, and `EnsureDiscovery`, commits the Access-derived cursor first and discovery checkpoint last. Create fans out its new ID; changed and equal Replace fan out their supplied valid ACL; EnsureDiscovery fans out the current ACL without revising Access. Users and groups are indexed, models are excluded, and discovery preserves first-discovery order without duplicate IDs. An unknown EnsureDiscovery is rejected. Any commit failure leaves the projection unavailable.
`discovery_missing(access_id, expected_subsystem)` is false for unknown IDs or a target in another subsystem; otherwise it reports whether any current named user/group owner/viewer lacks the ID. `discovered_for_user` and `discovered_for_group` return first-discovery order filtered to existing Access targets in the requested subsystem. These queries perform no authorization evaluation.
`owner_witness` and `check` preserve Access 0.2 semantics. `clear` clears Access state, discards discovery, and leaves the handle unavailable.
## Work and coordination
Open validates every Access row and its current named subjects. Apply performs expected-constant-time index work plus linear work in the action's subjects and commits Access before discovery. Discovery list filtering is linear in that subject's discovered IDs. Queries perform no I/O after open except discovery-store membership/list access. One apply mutex serializes callbacks; callers own no lock or cursor protocol.