Files
shopdb-flask/docs/adr/README.md
cproudlock 91143d94fb
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s
ADR-016: credential delivery to the fleet
Controller and share credentials are currently edited as cleartext into a
script on the SFLD share, one value for the whole fleet, re-applied by
GE-Enforce every cycle. Rotating means editing that file and hoping - nothing
reports which bays picked the new value up - and sites need per-bay variation,
which a manifest scope cannot express because scopes are per PC TYPE. A scope
per bay is a spreadsheet, not a model.

ShopDB therefore owns the definitions and the targeting, and a PC receives a
decided answer rather than rules to evaluate. Targeting uses the axes
GE-Enforce already filters on plus those the asset model knows: hostname
(including -like globs), machine, model, controller OS, PC type with alias
expansion, GE-Enforce profile, and a selector over the stored DNC projection -
"every machine whose DataHost is that share" is answerable from data already
held, and it also answers which machines need a credential at all.

Overlapping matches are guaranteed rather than exceptional, so precedence is
explicit: an integer priority, then scope specificity, then rule id for
stability. The resolver must be able to explain which rule won and why, or
nobody will trust it. It reuses plugins/geenforce/filters.py; there are already
two implementations of this matching logic kept honest by a parity harness, and
a third would drift silently.

Targeting stays separate from detection, mirroring PCTypes versus
DetectionMethod: who gets a credential is a server question, whether it is
already applied is a local one, and conflating them rewrites the secret every
cycle instead of healing drift.

Stored Fernet-encrypted with the key OUTSIDE the database, write-only through
the API and masked on read, fetched with a dedicated credentials.fetch scope so
a leaked collector key does not yield controller passwords, and every fetch
audited.

PROPOSED, not accepted: it makes ShopDB a credential store, and the key becomes
a single point of loss - restore the database without it and every credential
is unrecoverable, which docs/BACKUP-RESTORE.md must state in the same change
that implements this. Registry-only provisioning is recommended as a first step
regardless, since it removes the cleartext from the share immediately and the
client helper is identical either way.
2026-08-11 10:54:42 -04:00

36 lines
2.4 KiB
Markdown

# Architecture Decision Records
Each ADR captures a single architectural decision: the context, the decision itself, the consequences, and the alternatives considered. ADRs are immutable once accepted. Superseded ADRs stay in this folder with a pointer to the newer ADR.
## Status definitions
- **PROPOSED**: drafted, awaiting decision
- **ACCEPTED**: decision is in effect
- **SUPERSEDED**: replaced by a later ADR (link forward)
- **DEPRECATED**: no longer in effect, no replacement
## Index
| ADR | Title | Status |
|-----|-------|--------|
| [001](ADR-001-asset-as-platform-contract.md) | Asset model is the platform contract | ACCEPTED |
| [002](ADR-002-plugin-versioning.md) | Plugin contract versioning (semver) | ACCEPTED |
| [003](ADR-003-plugin-distribution.md) | Plugin distribution model | ACCEPTED |
| [004](ADR-004-deployment-topology.md) | Deployment topology (per-site instances) | ACCEPTED |
| [005](ADR-005-equipment-vs-measuringtools.md) | Equipment vs measuringtools plugin scope | ACCEPTED |
| [006](ADR-006-collector-contract.md) | Plugin collector contract pattern | ACCEPTED |
| [007](ADR-007-product-versioning-and-releases.md) | Product versioning and releases | ACCEPTED |
| [008](ADR-008-plugin-migration-ownership.md) | Plugin migration ownership (per-plugin chains) | ACCEPTED |
| [009](ADR-009-frontend-plugin-gating.md) | Frontend plugin route gating | ACCEPTED |
| [010](ADR-010-frontend-plugin-hooks.md) | Frontend plugin hook contract | ACCEPTED |
| [011](ADR-011-machines-rename.md) | Machines rename + modeltypes retyping | ACCEPTED |
| [012](ADR-012-geenforce-manifest-ownership.md) | GE-Enforce manifest ownership in shopdb | ACCEPTED |
| [013](ADR-013-plugin-catalog-and-lean-builds.md) | Plugin catalog, curated shelf, and lean per-site builds | PROPOSED |
| [014](ADR-014-schema-lean-per-site.md) | Schema-lean per-site builds (retire cross-plugin FKs, prune not-installed plugin tables) | ACCEPTED |
| [015](ADR-015-site-specific-configuration.md) | Where a site's own data is allowed to live (setting, site directory, or seed) | ACCEPTED |
| [016](ADR-016-credential-delivery.md) | Credential delivery to the fleet (ShopDB-resolved targeting, encrypted at rest) | PROPOSED |
## Authoring
When proposing a new decision, copy the most recent ADR as a template, increment the number, and update this index. Do not edit accepted ADRs in place; supersede them with a new one.