Skip to content

RFC-0001: v0.1 implementation plan

Status: Implemented Author: Alex Nodeland Created: 2026-10-12 Discussion: derived from lattice RFC-0001, accepted on 2026-10-12 with its decisions D1 to D9 Siblings:

Summary

grantr is identity and access for lattice, as lattice RFC-0001 designs it: tenants, members, groups, roles, service principals and grants, checked through the libraries' widened hooks, with an append-only audit log, in-memory and SQL adapters, and an admin API. This RFC is grantr's plan for v0.1: the design's seven phases, after a foundation, with the modules each phase adds, where its work lands, and what it waits on. The design itself is lattice RFC-0001's and is not repeated here.

Motivation

Lattice RFC-0001 is lattice's document, and its phases change artifactr, reflexr, relayr and stackr's template as well as grantr. grantr needs a plan in its own section that its pull requests reference and tick, and that says which work is grantr's.

Design

Modules

Module Holds Phase Extra
grantr.core The model and its types (subjects, resources, roles, grants, memberships, visibility, the audit events), grantr's catalog, the built-in roles, the rules a check and a grant follow, and service principal keys, grantr_sk_<id>_<secret>, minted and verified by digest: no I/O 2
grantr.grants Grants, with check, hidden, member, memberships, resources and hooks, and the commands that change access, each audited; the storage port and its in-memory adapter, with one contract test for every adapter 2
grantr.sql The SQL adapter: SQLAlchemy, Alembic migrations and grantr_-prefixed tables in the application's schema 3 sql, sqlite, postgres
grantr.fastapi grantr_router, with GET /grantr/v1/me and POST /grantr/v1/checks, and its OpenAPI document committed in schemas/ 3 fastapi
grantr.telemetry Spans for checks over a threshold, counters of allowed and refused checks by action, and the audit events, through the OpenTelemetry API 3
grantr.testing matrix(catalogs, roles), every role against every action, which the template commits as a snapshot 4

Phase 4 defers the on_tenant_created callback, which would create a tenant's gateway team and key: the template's gateway keys are settings, and stackr's make tenant creates the team (ADR-0021).

Lattice RFC-0001 names no phase for telemetry; it lands with the API in phase 3, since the refusals it counts are the router's as well as the hooks'. A module's name may change when it is built; grantr's architecture page, from phase 2, describes what exists.

Prerequisites

As of 2026-10-12:

Prerequisite Lands in Needed by State
The widened hook: Access, ACTIONS, the hooks on Workspaces, on_behalf_of (lattice RFC-0001's phase 1) artifactr, reflexr phases 4 and 5 Done (#59, #61)
reflexr's stored rules, whose allow phase 1 folds into the hook reflexr phase 1 Done
A tenant's workspaces listed (#5) artifactr none; whether its listing comes from grantr is an unresolved question Open

Phases 1 and 2 are independent, so grantr's core is built against the hook's shape in lattice RFC-0001, not its code: it reads an Access's fields by name, and takes actors as they come.

Phases

Phase Deliverable Lands in Waits on Exit criteria
0. Foundation The package, its tooling and release configuration, its site section, ADRs for D1 to D9, and this plan grantr Nothing CI green at 100% coverage, and the site builds in strict mode
1. The hook Access, the widened Authorize, OnOpen and ACTIONS, held by Workspaces; on_behalf_of; a check in every Workspace method; StoredRules.allow folded in; one author per turn; the matrix tests; the template's mirrors on on_open artifactr, reflexr and stackr's template Nothing Every library's matrix test passes, and a template application behaves as before with an allow-all hook
2. grantr's core grantr.core and grantr.grants: the model and types, built-in and custom roles, groups, service principals and keys, check, resources, hooks and SubjectOf, the audit log, and the in-memory adapter, with the contract test grantr Nothing In the contract test, a viewer is refused an edit, a key can't reach another tenant, and no one grants more than they hold
3. Storage and API grantr.sql and its migrations; grantr.fastapi and its committed OpenAPI document, with the list reads the router needs (a tenant's members, groups, grants and keys, and every tenant for operators); grantr.telemetry grantr Phase 2 The contract test passes on SQLite and PostgreSQL, and the drift test passes
4. The template The access question, tenancy from memberships, keys, make tenant, make operator, make migrate-tenants; grantr.testing and the matrix snapshot stackr's template and grantr Phases 1 to 3 A generated application passes its CI, and the smoke test signs a user in to one of two tenants and is refused the other
5. Threads and artifacts Visibility and Hidden in artifactr, every read path filtered, the restricted flag in grantr, and turns that act for their user artifactr and grantr Phases 1 to 4 A restricted thread is absent from every surface for a non-member, including the agent's tools in another user's turn
6. Row-level security The option in artifactr's, reflexr's, relayr's and grantr's SQL adapters, the second engine, and the template's non-owner role artifactr, reflexr, relayr, grantr and stackr's template Phase 3 With the libraries' tenant scoping bypassed in a test, PostgreSQL returns no other tenant's rows, and reflexr's scheduler still runs every tenant's due runs
7. Docs and ADRs grantr's guides, reference and architecture, the ADRs for the amendments, and grantr's README grantr, and the amended packages' sections Phases 1 to 6 grantr's section builds, with the architecture updated

Each phase is a series of small pull requests to main, and a phase that lands in grantr brings its guides, reference pages, architecture and ADRs with it. Phase 2's hidden hides nothing: the restricted flag it reads comes in phase 5.

Drawbacks

  • Half the plan lands elsewhere. Phases 1, 4, 5 and 6 change artifactr, reflexr, relayr and stackr's template, so this checklist tracks work its own pull requests don't contain.
  • The core comes before the hook it answers. Phase 2 builds hooks against the hook's shape in the design, and phase 1 may refine names that phase 4 then adapts to.

Alternatives

Lattice RFC-0001 weighs the engine, where membership lives and where access is checked, in its Alternatives and Decisions. For the plan itself, tracking grantr's work in lattice RFC-0001's checklist alone would keep one list, but grantr's own pull requests and issue couldn't then say which phases are grantr's.

Unresolved questions

Lattice RFC-0001's own open questions stand: a stored rule's grants at install, ending a live connection on revocation, and workspaces without a library behind them. One more is the libraries':

  • How the libraries accept grantr's Visibility. grantr imports neither library, so its hidden returns its own Visibility, with the same fields as artifactr's. Phase 5 types artifactr's Hidden so that grantr's answer satisfies it.

Tracking

The tracking issue is #47.

  • Phase 0: foundation
  • Phase 1: the hook (artifactr, reflexr and stackr's template)
    • artifactr and the template's collaboration (#59)
    • reflexr and the template's automation (#61)
  • Phase 2: grantr's core (ADR-0010 to ADR-0015)
  • Phase 3: storage and API (ADR-0016 to ADR-0018)
  • Phase 4: the template (ADR-0019 to ADR-0022; stackr ADR-0019)
  • Phase 5: threads and artifacts
  • Phase 6: row-level security
  • Phase 7: docs and ADRs (ADR-0001 to ADR-0009 recorded in phase 0)