# Architecture Decision Records An ADR captures one decision: the context, the decision, the consequences and the alternatives. ADRs are immutable once accepted. A superseded ADR stays in this folder, marked at the top, pointing forward. **Read the index, not the folder.** Find the one line that matches your question, open that ADR, and skip the rest. Nothing here is a prerequisite for anything else. ## Which decision governs your question | ADR | The question it answers | Holds? | |---|---|---| | [001](ADR-001-asset-as-platform-contract.md) | What may a plugin depend on? What is the versioned platform surface? | In force | | [002](ADR-002-plugin-versioning.md) | How is that surface versioned, and what does a plugin's `core_version` mean? | In force | | [003](ADR-003-plugin-distribution.md) | How does a plugin reach a site - bundled, or from its own repo? | In force. ADR-013 added the catalog, artifact and signing on top | | [004](ADR-004-deployment-topology.md) | One instance per site, or one multi-tenant instance for all sites? | In force, except its "Migration strategy" section, replaced by ADR-008 | | [005](ADR-005-equipment-vs-measuringtools.md) | Are metrology instruments a separate asset class from machinery? | **Superseded by [018](ADR-018-metrology-instruments-are-machines.md).** Answer reversed | | [006](ADR-006-collector-contract.md) | How does a plugin accept data pushed in from outside? | In force | | [007](ADR-007-product-versioning-and-releases.md) | What version is the PRODUCT, as distinct from the plugin contract? | In force | | [008](ADR-008-plugin-migration-ownership.md) | Whose Alembic chain owns a plugin's tables? | In force | | [009](ADR-009-frontend-plugin-gating.md) | What happens when someone opens a URL belonging to a disabled plugin? | In force | | [010](ADR-010-frontend-plugin-hooks.md) | How does a plugin add UI without editing core Vue files? | In force | | [011](ADR-011-machines-rename.md) | Why is the code called `machines` and what happened to `machinetypes`? | In force | | [012](ADR-012-geenforce-manifest-ownership.md) | Does ShopDB own GE-Enforce manifests, and does it own the engine? | **Record only on this line.** The plugin it decided is not bundled here; ADR-013 and the API-token resource scopes trace back to it | | [013](ADR-013-plugin-catalog-and-lean-builds.md) | How does a site ship only the plugins it chose, and how is plugin code trusted? | In force | | [014](ADR-014-schema-lean-per-site.md) | Does a lean site still create tables for plugins it never installed? | In force | | [015](ADR-015-site-specific-configuration.md) | Where may one site's hostnames, shares and defaults live? | In force | | [016](ADR-016-credential-delivery.md) | How does a bay get a controller credential without a cleartext file on a share? | **Superseded by [019](ADR-019-per-pc-endpoint-credentials.md), and never built.** Do not build against it | | [017](ADR-017-buildings-and-levels.md) | How does the floor map hold more than one floor and more than one building? | In force | | [018](ADR-018-metrology-instruments-are-machines.md) | Where do CMMs and vision systems live now that `measuringtools` is retired? | In force, and this line is the one it describes: there is no measuring-tool asset class | | [019](ADR-019-per-pc-endpoint-credentials.md) | How does the server know WHICH PC is calling, and what replaced the fleet-wide key? | In force | Related decisions that are not ADRs, kept as records of why something was built: [docs/proposals](../proposals/README.md). ## Status vocabulary The `Status:` line at the top of each ADR uses these, and nothing else: - **PROPOSED** - drafted, awaiting decision. - **ACCEPTED** - in effect. - **SUPERSEDED by ADR-NNN** - replaced. The link forward is part of the status, and the superseded ADR carries a note at the top saying not to build against it and what changed. - **DEPRECATED** - no longer in effect, with no replacement. ## Authoring 1. Copy the most recent ADR as a template and increment the number. 2. Start the file with a `docmeta` comment, before the H1. ADRs are `purpose: explanation`. 3. Add a row to the table above: the QUESTION it answers, not its title. 4. Add it to [docs/INDEX.md](../INDEX.md) too - under "Decisions" while it is current, under "Archive" once it is superseded. It has to be a table ROW with its real line count, not a mention in a paragraph: `tests/test_docs_index.py` fails on an ADR no row routes to, and on a row whose line count is stale. 5. Never edit an accepted ADR's decision. Supersede it with a new one, and mark the old one at the top - ADR-005 and ADR-016 are the worked examples.