- new backend.md §"Registry types and schemas": RepoRecord serde shape
(three-action grants per ADR-015, opaque grant keys, storage_root
omitted from all op responses per ADR-008); the five-variant
RegistryError set with wire mappings; the four git/repo/* op
request/response schemas with additionalProperties: false inputs and
the git:repo:* error-code namespace
- the not_found/forbidden collapse carries one wire code ('unauthorized')
per N-2's rule; AlreadyExists is create-side only (no existence oracle)
- OQ-03 inventory note + review 001 N-3 marked resolved — review 001 is
now 14/14
verification: cargo test, clippy -D warnings, fmt --check, doc,
publish --dry-run — clean
240 lines
13 KiB
Markdown
240 lines
13 KiB
Markdown
---
|
||
status: draft
|
||
last_updated: 2026-09-25
|
||
---
|
||
|
||
# Open Questions
|
||
|
||
All unresolved architecture questions, centrally tracked. Status values:
|
||
`open` (needs resolution now), `partially resolved` (decision made but a
|
||
narrower question remains — named in the entry), `resolved` (decision
|
||
made, ADR recorded), `deferred(scope)` (waiting on external information —
|
||
blocked-on condition stated), `deferred(unclear)` (pieces exist, shape
|
||
needs investigation). See `docs/sdd_process.md` for the deferral protocol
|
||
(blocker tasks in `tasks/architecture/`).
|
||
|
||
**Door type** classifies reversal cost: `one-way` decisions are
|
||
expensive/impossible to reverse once published (wire formats, public API
|
||
shapes); `two-way` decisions can be revisited while nothing is published.
|
||
Door type does not change urgency — all decisions here need resolution
|
||
when their impacts say so; it records how careful the resolution must be.
|
||
|
||
## Deferred / Blocked summary
|
||
|
||
| OQ | Status | Blocked on / investigation |
|
||
|---|---|---|
|
||
| OQ-05 | deferred(scope) | ecosystem need for sha256 |
|
||
| OQ-03 | partially resolved | first-publish timing (release decision; the freeze inventory lives in backend.md/transport.md) |
|
||
| OQ-16 | deferred(scope) | first cross-assembly record sharing (distributed-git phase; tracker `architecture/oq-16-grant-identity-namespace`) |
|
||
|
||
OQ-02 and OQ-04 resolved this cycle (ADR-014, ADR-013); OQ-08/06/07/09/01
|
||
resolved in earlier cycles. OQ-16 is deferred but blocks nothing in v1
|
||
(grants key on cluster-local ids within one assembly).
|
||
|
||
## Theme: composition / crate shapes
|
||
|
||
### OQ-09: Slim-crate model — doors as family infrastructure, git as a payload service
|
||
|
||
- **Origin**: user session (2026-09-21); ADR-006, ADR-001, ssh.md
|
||
- **Status**: **resolved** — ADR-010 (pure protocol crate, the alktty/
|
||
alktunnels template): single `alkgit` crate, producer/consumer halves,
|
||
backend traits with feature-gated gix, no doors, no binary; ALPN
|
||
`alk/git`; http mounting → alkhttp `git` feature; git-over-ssh →
|
||
alkssh (russh scaffolding dropped); the monorepo/binary framing was an
|
||
init-agent artifact (vision amended).
|
||
- **Resolution**: [decisions/010-pure-protocol-crate.md]. All five
|
||
sub-decisions recorded there (ssh deletion, http home, crate
|
||
granularity, backend-trait surface, binary fate).
|
||
- **Cross-references**: ADR-001/006 (superseded), OQ-01, OQ-03, OQ-08,
|
||
doors.md, backend.md, overview.md
|
||
|
||
### OQ-01: HTTP adapter home and composability (alkhttp `git` feature vs alkgit-owned factory)
|
||
|
||
- **Origin**: user session question (OQ-01, resolved 2026-09-21)
|
||
- **Status**: **resolved** (subsumed by OQ-09/ADR-010) — the smart-http
|
||
stateless substrate stays in `alkgit` (IO-abstract); the http mounting
|
||
(routes, content types, `with_extra_routes` wiring) becomes an alkhttp
|
||
`git` feature published after alkgit's first publish. The ADR-006
|
||
router-factory shape is superseded; the alkhttp-side feature is the
|
||
outcome.
|
||
- **Cross-references**: ADR-006 (superseded), ADR-010, doors.md
|
||
|
||
### OQ-03: Downstream embedding surface (what "embeds alkgit" means concretely)
|
||
|
||
- **Origin**: [overview.md], [transport.md], vision §"ALPN as a service"
|
||
- **Status**: **partially resolved** — the shape is settled (ADR-010):
|
||
embedding = one crate + backend traits (own storage via
|
||
`default-features = false`, or the `gix`/`registry-file` features) +
|
||
optional door features. What remains deferred is the publish-time API
|
||
freeze itself: which type/feature/op names are pinned at first
|
||
crates.io publish. ADR-012 added the `git/repo/*` op set (names +
|
||
schemas) to the freeze inventory; ADR-013/014 added the push/negotiation
|
||
trait surface (`GitPackIngest` binding, `GitPackGen::common_haves`);
|
||
ADR-016 added the native-path preamble wire shapes (the `{repo,
|
||
service}` open-op params schema and the git-daemon request-line
|
||
grammar — the last native-path wire surface); ADR-017 added the
|
||
`GitSession` public API; the registry types/schemas draft
|
||
(backend.md §"Registry types and schemas", review 001 N-3) pinned
|
||
`RepoRecord`, `RegistryError`, and the `git/repo/*` op schemas.
|
||
- **Door type**: one-way (API freeze is registry-visible to dependents)
|
||
- **Priority**: medium
|
||
- **Impacts**: blocks the first publish only, not implementation.
|
||
- **Blocked on**: first-publish timing (a release decision, not an
|
||
architecture question). The API surface inventory lives in
|
||
[backend.md](backend.md) §public API and [transport.md](transport.md)
|
||
§public API. ADR-013/014 added the push/negotiation trait surface
|
||
(`GitPackIngest` binding, `GitPackGen::common_haves`) to the freeze
|
||
inventory; ADR-016 added the native preamble wire shapes.
|
||
- **Cross-references**: ADR-010, ADR-002, ADR-012, ADR-013, ADR-014,
|
||
ADR-016, backend.md, transport.md
|
||
|
||
## Theme: transport / protocol
|
||
|
||
### OQ-02: V2 multi-round negotiation (ack/NAK logic, `wait-for-done` retirement)
|
||
|
||
- **Origin**: [transport.md], poc2-findings §"does NOT settle"
|
||
- **Status**: **resolved** — ADR-014 (V2 negotiation ack loop). The
|
||
duplex-capture walkthrough against git 2.43.0 (ground-truth negotiation
|
||
mock, cross-checked against `fetch-pack.c`) resolved the grammar: no-
|
||
`done` rounds get `acknowledgments` (`ACK <oid>` per recognized have,
|
||
`NAK` when none, flush — never `ready`, so FLUSH is always the
|
||
terminator); the `done` round generates closure(wants) − closure(haves)
|
||
with no cross-round server state (clients re-send wants + commons every
|
||
round); `wait-for-done` stays and the advertisement text is unchanged;
|
||
the ack check is a new backend-trait method (`common_haves`) keeping
|
||
the honest boundary at the seam. Captures:
|
||
`docs/research/negotiation-captures.md`.
|
||
- **Resolution**: [decisions/014-v2-negotiation-ack-loop.md]
|
||
- **Cross-references**: ADR-003, ADR-004, ADR-005, ADR-009, ADR-014,
|
||
transport.md §fetch, backend.md §"The trait family" (GitPackGen)
|
||
|
||
### OQ-04: receive-pack (push) — validation gap
|
||
|
||
- **Origin**: [transport.md], poc3-findings §"does NOT settle"
|
||
- **Status**: **resolved** — ADR-013 (receive-pack state machine). The
|
||
walkthrough against real `git push` captures (git 2.43.0: file://,
|
||
git://, smart-http, plus raw stdio requests into real `git receive-pack`)
|
||
resolved every listed unknown: the push path is V0-framed by upstream
|
||
design (no version negotiation, ADR-003 governs fetch only); the
|
||
advertisement is a V0-shaped ref advertisement (caps on the first ref
|
||
line, `capabilities^{}` sentinel only for empty repos) with served set
|
||
`report-status(-v2) delete-refs side-band-64k atomic ofs-delta
|
||
object-format=sha1` (+ `push-options` config-gated); shallow request
|
||
lines are rejected up front for v1 (symmetric with fetch); thin packs
|
||
accepted with bases from the server odb (default client behavior, no
|
||
capability); ingestion = `Bundle::write_to_directory_eagerly` +
|
||
`gix-fsck` + one `gix-ref` transaction per push (`.keep`-guarded pack
|
||
landing); CAS timing is unpack-first-then-per-ref (observed upstream
|
||
order); status report is band-1 pkt-line-framed with inner flush when
|
||
sideband was selected. Captures:
|
||
`docs/research/push-captures.md`.
|
||
- **Resolution**: [decisions/013-receive-pack-state-machine.md]
|
||
- **Cross-references**: ADR-003, ADR-004, ADR-005, ADR-009, ADR-013,
|
||
transport.md §receive-pack, backend.md §"The trait family" (GitRefs,
|
||
GitPackIngest), doors.md
|
||
|
||
### OQ-05: sha256 support policy
|
||
|
||
- **Origin**: [transport.md], git-protocol.md §"Open items"
|
||
- **Status**: deferred(scope)
|
||
- **Door type**: two-way
|
||
- **Priority**: low
|
||
- **Impacts**: none for v1 (sha1 pinned); feature-flag passthrough
|
||
compiles but is untested end-to-end.
|
||
- **Blocked on**: ecosystem need (a real client/repo requiring sha256) or
|
||
upstream gix sha256 maturity; POC-2 left the pipeline hash-generic but
|
||
untested. Tracker task: `tasks/architecture/oq-05-sha256.md`.
|
||
- **Cross-references**: ADR-003, ADR-004
|
||
|
||
## Theme: identity / auth
|
||
|
||
### OQ-08: Registry identity space + vault placement (narrowed)
|
||
|
||
- **Origin**: [overview.md], [doors.md], [backend.md]; originally "identity
|
||
sources per front door"
|
||
- **Status**: **resolved** — ADR-011 (per-repo authorization): the
|
||
identity model is alkcall's resolved `Identity` keyed on its stable
|
||
logical id (alkcall ADR-025 property, referenced); alkgit stores no
|
||
identity records; grants live in repo records; the public+read /
|
||
always-authenticated-write policy is alkgit-core's `authorize`
|
||
function (the clause ADR-007 pinned but the static ACL engine could
|
||
not express); vault placement resolved as **nothing to place in v1**
|
||
(no credential-shaped material in metadata).
|
||
*(Grant-key id format declared deliberately open by ADR-015 §7 — the
|
||
cross-identity-namespace question this leaves is tracked as OQ-16.)*
|
||
- **Resolution**: [decisions/011-per-repo-authorization.md]
|
||
- **Cross-references**: ADR-007, ADR-008, ADR-011, ADR-012, OQ-06, OQ-07,
|
||
backend.md §GitRegistry, doors.md
|
||
|
||
### OQ-16: Grant-key identity namespace (globally-comparable ids for multi-hub grants)
|
||
|
||
- **Origin**: ADR-015 §7; user session (2026-09-26)
|
||
- **Status**: deferred(scope)
|
||
- **Door type**: two-way (schema field format; grants are already opaque
|
||
strings, so this constrains only the *contents*, not the alkgit API)
|
||
- **Priority**: low (blocks nothing in v1 — grants key on alkcall's
|
||
cluster-local id within one assembly, which is the only deployment
|
||
v1 serves)
|
||
- **Question**: what identity-id format do grants key on when repo
|
||
records are shared across assemblies (the distributed/replicator
|
||
deployment: contract-watching hubs mirroring grant state)? Today the
|
||
id is alkcall's `Identity.id` — stable within one cluster, but
|
||
meaningless across hubs. Candidate shapes: `{namespace}/{id}`
|
||
compound ids (the `{user|org}/{repo}` convention familiar from
|
||
self-hosted git — e.g. `alkdev/alkgit` locally, `alkimiadev/alkgit`
|
||
when mirrored — extended to identity: `gh:alkimiadev`,
|
||
`alk:alkdev`), did-key / contract-derived identifiers (the planned
|
||
smart-contract org/user/repo model), or a two-part
|
||
(authority, local-id) tuple.
|
||
- **Constraints any resolution must satisfy** (recorded from ADR-015 §7):
|
||
grants remain flat sets keyed on opaque strings; alkgit never parses,
|
||
validates, or interprets the id — collision-freedom is the
|
||
identity-provider's guarantee; a downstream namespace can be
|
||
introduced at the assembly seam without an alkgit change.
|
||
- **Impacts**: only the downstream identity-provider seam and the
|
||
future platform app / replicator grant-sync format. The v1
|
||
`authorize` policy function, the grant schema shape, and the op gate
|
||
are all id-format-agnostic by construction.
|
||
- **Blocked on**: the first deployment that shares repo records across
|
||
assemblies (the distributed-git phase; also touches alkcall's
|
||
identity model if a family-wide id format is preferred over a
|
||
payload-level namespace convention). Tracker task:
|
||
`tasks/architecture/oq-16-grant-identity-namespace.md`.
|
||
- **Cross-references**: ADR-011 §1, ADR-015 §7, OQ-08
|
||
|
||
## Theme: storage / metadata
|
||
|
||
### OQ-06: Registry/metadata backing store (gix feature)
|
||
|
||
- **Origin**: [backend.md] (was storage.md), ADR-008
|
||
- **Status**: **resolved** — ADR-012 (registry backing + write surface):
|
||
the alknet repo/adapter pattern applied — `GitRegistry` read trait +
|
||
`GitRegistryStore` write supertrait; default backing is the
|
||
`registry-file` feature (per-repo record files + in-memory index,
|
||
config-seeded, op-mutable, atomic writes — no gitoxide); persistence
|
||
adapters (SQLite et al.) are future, separate, additive, gated by a
|
||
real deployment need — the deferred "scale requirements" never gated
|
||
the default, only that future adapter.
|
||
- **Resolution**: [decisions/012-registry-backing-and-ops.md] §1–2, §4
|
||
- **Cross-references**: ADR-008, ADR-010 (feature story amended), ADR-011,
|
||
backend.md §feature model
|
||
|
||
### OQ-07: Admin API operation set (v1 scope)
|
||
|
||
- **Origin**: [overview.md], alk-stack.md §"The gitea lesson"
|
||
- **Status**: **resolved** — ADR-012 (§3, §5): the crate ships a minimal
|
||
CRUD op set (`git/repo/{create,delete,update,get}`) as thin call ops
|
||
over `GitRegistryStore`, `Visibility::External`, always-on, gated by
|
||
the global admin scope and per-repo grants. The old "Internal ops over
|
||
an admin listener" framing is superseded (right mechanism, wrong axis
|
||
— visible-surface = authorized-surface is served by the ACL). The
|
||
gate table as written used scope+ownership and is replaced by ADR-015
|
||
(the `manage` grant tier — admin scope OR manage grant, handler-
|
||
evaluated; create seeds the creator's `{read, write, manage}` grants).
|
||
Ops stay record-scoped; anything beyond repo records (users, orgs) is
|
||
a downstream platform crate (the recorded split trigger, ADR-012 §5) —
|
||
the app compiles roles/teams into flat grants (ADR-015 §6).
|
||
- **Resolution**: [decisions/012-registry-backing-and-ops.md] §3, §5
|
||
(gate amended by [decisions/015-manage-grant-and-op-gate.md])
|
||
- **Cross-references**: ADR-007, ADR-011, ADR-012, ADR-015, alkcall
|
||
ADR-017/011, backend.md §"The two op kinds" |