|
| 1 | +# ADR-0001: Withdrawn — this number is retired and must not be reused |
| 2 | + |
| 3 | +**Status**: **Withdrawn (2026-02-11)**. This file is a *tombstone*, not a decision: nothing in it is in force, and the number must never be reassigned. |
| 4 | +**Deciders**: ObjectStack Protocol Architects (recorded retroactively — see [How this differs from ADR-0107](#how-this-differs-from-adr-0107)) |
| 5 | +**The record that held this number**: *"Metadata Service Architecture"* — `docs/adr/0001-metadata-service-architecture.md`, Status *Accepted (2026-02-10)* |
| 6 | +**Landed by**: `908d95c82`, 2026-02-10 09:14 UTC |
| 7 | +**Deleted by**: `9da8e3e72`, 2026-02-11 23:35 +0800, about thirty hours later — a 37-path documentation sweep, not an ADR decision |
| 8 | +**Tracking**: [#7329](https://github.com/objectstack-ai/objectstack/issues/7329) (the citation-resolution work that named this case), [#7866](https://github.com/objectstack-ai/objectstack/issues/7866) (this tombstone), [#6634](https://github.com/objectstack-ai/objectstack/issues/6634) (the squat failure mode both are written against) |
| 9 | +**Consumers**: none. No code is governed by this number, and none may be — see [Do not anchor to this number](#do-not-anchor-to-this-number). |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## TL;DR |
| 14 | + |
| 15 | +A real record occupied ADR-0001 on `main` for about thirty hours in February 2026 and |
| 16 | +was then deleted. Unlike [ADR-0107](./0107-withdrawn-hook-body-write-set-static-gap.md), |
| 17 | +it was **not withdrawn on the merits** — it was swept away as collateral in a bulk |
| 18 | +documentation cleanup that took the entire `docs/adr/` registry with it, including its |
| 19 | +`README.md` and the ADR-0002 of that era. |
| 20 | + |
| 21 | +This file exists so the number resolves to that explanation instead of to nothing, and so |
| 22 | +it is never handed to an unrelated decision. Reassigning it would retroactively re-point |
| 23 | +every historical "ADR-0001" at a document its author never meant — the squat failure mode |
| 24 | +[#6634](https://github.com/objectstack-ai/objectstack/issues/6634) was filed for, where |
| 25 | +one number had silently accumulated 77 citations it did not resolve. |
| 26 | + |
| 27 | +**A new record takes the next free number. Not this one.** |
| 28 | + |
| 29 | +## What happened |
| 30 | + |
| 31 | +| When | What | Evidence | |
| 32 | +|---|---|---| |
| 33 | +| 2026-02-10 09:14 UTC | `docs/adr/0001-metadata-service-architecture.md` written and merged, Status *Accepted*, authored by an automated agent | `908d95c82` | |
| 34 | +| 2026-02-11 23:35 +0800 | Deleted, together with `docs/adr/0002-database-driven-metadata-storage.md` and `docs/adr/README.md`, inside a 37-path docs sweep | `9da8e3e72` | |
| 35 | +| 2026-08-08 | The bare number is grandfathered onto `check-adr-anchors`'s citation allowlist, pending this tombstone | [#6634](https://github.com/objectstack-ai/objectstack/issues/6634) | |
| 36 | +| 2026-08-11 | [PR #7838](https://github.com/objectstack-ai/objectstack/pull/7838) makes a tombstone refuse *anchors* while still resolving *citations*, and leaves this number open because it needs a file under `docs/adr/` | [#7329](https://github.com/objectstack-ai/objectstack/issues/7329) | |
| 37 | + |
| 38 | +The deleting commit's subject is *"feat(docs): add comprehensive analysis of Permission |
| 39 | +Protocol with AI-enhanced security controls and RLS implementation"*; its body is empty |
| 40 | +and it names no ADR. Alongside the registry it removed the whole `docs/METADATA_*` |
| 41 | +documentation family and the `examples/metadata-objectql` package. **No reasoning for |
| 42 | +retiring the decision was recorded anywhere**, which is the substantive difference from |
| 43 | +ADR-0107 and the reason this tombstone reconstructs the record from the tree rather than |
| 44 | +quoting a withdrawal. |
| 45 | + |
| 46 | +## Do not resurrect it |
| 47 | + |
| 48 | +Independently of how it was deleted, the record's substance is now **contradicted by |
| 49 | +shipped code**, so restoring the text would plant a false statement in the decision log. |
| 50 | + |
| 51 | +Its selected option was a **hybrid dual-provider** architecture: *both* `@objectstack/objectql` |
| 52 | +and `@objectstack/metadata` may provide the `metadata` service, MetadataPlugin taking |
| 53 | +precedence when loaded and **ObjectQL registering itself as the fallback provider** when |
| 54 | +it is not. That fallback is exactly what the code stopped doing: |
| 55 | + |
| 56 | +- **MetadataPlugin is the sole provider** of the `metadata` service — the one |
| 57 | + `registerService('metadata', …)` in the tree is |
| 58 | + [`packages/metadata/src/plugin.ts`](../../packages/metadata/src/plugin.ts). |
| 59 | +- **ObjectQL is a consumer, never a provider.** |
| 60 | + [`packages/objectql/src/plugin.ts`](../../packages/objectql/src/plugin.ts) registers |
| 61 | + `objectql`, `data`, `manifest` and `lifecycle` — and no longer `metadata`. It reads the |
| 62 | + `metadata` service and degrades to its own internal registry when none is present, |
| 63 | + which is not the same thing as claiming the slot. |
| 64 | +- **The shared-interface principle survived, as a spec contract**: `IMetadataService` in |
| 65 | + [`packages/spec/src/contracts/metadata-service.ts`](../../packages/spec/src/contracts/metadata-service.ts). |
| 66 | + |
| 67 | +The live account of that surface is the "Metadata service architecture" section of |
| 68 | +[`ARCHITECTURE.md`](../../ARCHITECTURE.md). Read that, never this file, for what is true |
| 69 | +today. The withdrawn text is recoverable in full at |
| 70 | +`git show 908d95c82:docs/adr/0001-metadata-service-architecture.md` and is deliberately |
| 71 | +kept in history rather than reprinted here — a withdrawn record reprinted inside its own |
| 72 | +tombstone reads as a record. |
| 73 | + |
| 74 | +Note that the single-provider architecture which replaced it **has no ADR record of its |
| 75 | +own**. That gap is real and is not closed by this file; re-homing it is a maintainer call. |
| 76 | + |
| 77 | +## What ADR-0002 actually cites |
| 78 | + |
| 79 | +Recorded because it is the first thing a reader arriving from ADR-0002 will want, and |
| 80 | +because it was mis-stated in `check-adr-anchors.mjs` until this tombstone was written. |
| 81 | + |
| 82 | +[`0002-environment-database-isolation.md`](./0002-environment-database-isolation.md) says, |
| 83 | +of a rejected alternative: *"One global DB + tenant column. Was never on the table — |
| 84 | +already discarded in v3.4's ADR-0001."* That is **not** a reference to the record above. |
| 85 | +The record that held this number decided how the `metadata` *service* is registered and |
| 86 | +says nothing about tenancy or database topology. |
| 87 | + |
| 88 | +Two distinct things carry the string "ADR-0001" in this repository's past, and only one |
| 89 | +of them was ever a file here: |
| 90 | + |
| 91 | +- **The v3.4-era "ADR-0001" ADR-0002 is pointing at.** Nothing matching `*0001-*` was ever |
| 92 | + added under any path, on any branch, other than the metadata-service record — see |
| 93 | + [Archaeology](#archaeology). Today's ADR-0002 is itself dated 2026-04-19 and supersedes |
| 94 | + the v3.4/v4.0 per-organization database model, so its "v3.4's ADR-0001" is a reference to |
| 95 | + a pre-registry document that this repository has never contained. |
| 96 | +- **`docs/adr/0001-metadata-service-architecture.md`**, the record this tombstone retires. |
| 97 | + |
| 98 | +The citation is therefore historical narration rather than a pointer into `docs/adr/`, and |
| 99 | +this file is what it now resolves to. Correcting ADR-0002's wording is an edit to an |
| 100 | +accepted record and is deliberately not made here. |
| 101 | + |
| 102 | +## Do not anchor to this number |
| 103 | + |
| 104 | +`scripts/check-adr-anchors.mjs` requires every `ADR-NNNN` cited in a tracked file to name a |
| 105 | +record under `docs/adr/`. This tombstone satisfies that check — deliberately, because the |
| 106 | +citations below are legitimate references to a deleted record. It is **not** a licence to |
| 107 | +cite ADR-0001 as governing anything: an anchor entry must state the invariant its ADR |
| 108 | +decided, and this number decides nothing today. |
| 109 | + |
| 110 | +The citations that exist are all discussion of the deletion itself: |
| 111 | + |
| 112 | +- [`ARCHITECTURE.md`](../../ARCHITECTURE.md) — names the deleted path as plain text and |
| 113 | + states the current single-provider architecture in its place; |
| 114 | +- [`0002-environment-database-isolation.md`](./0002-environment-database-isolation.md) — |
| 115 | + the v3.4 reference dissected above; |
| 116 | +- `scripts/check-adr-anchors.mjs` — the gate, describing this case. |
| 117 | + |
| 118 | +## Archaeology |
| 119 | + |
| 120 | +Recorded so the next reader does not repeat it. Run against full history with the clone |
| 121 | +**unshallowed** — a shallow clone silently answers "never existed", and the default clone |
| 122 | +in this project's agent containers is 50 commits deep: |
| 123 | + |
| 124 | +```bash |
| 125 | +git fetch --unshallow |
| 126 | +git log --all --diff-filter=AD -- 'docs/adr/0001*' # -> exactly 2 commits, both above |
| 127 | +git log --all --diff-filter=AD -- '*0001-*' # -> the same 2 commits, any path |
| 128 | +git log --all --oneline -S'ADR-0001' # -> 10 commits, all accounted for |
| 129 | +``` |
| 130 | + |
| 131 | +**Nothing else ever claimed this number**, on any branch, at any time: the second query |
| 132 | +widens the first from `docs/adr/` to the whole tree and returns the same two commits, so |
| 133 | +there is no second era of "ADR-0001" as a file and no lost content beyond the record named |
| 134 | +above. |
| 135 | + |
| 136 | +## How this differs from ADR-0107 |
| 137 | + |
| 138 | +Both are tombstones and both are unreusable, but the two cases are not the same and the |
| 139 | +distinction is worth keeping: |
| 140 | + |
| 141 | +| | ADR-0107 | ADR-0001 | |
| 142 | +|---|---|---| |
| 143 | +| Why it left | Owner decision, reasoning stated in the withdrawing commit | Collateral in an unrelated 37-path docs sweep; no reasoning recorded | |
| 144 | +| Lifetime | Nine hours | About thirty hours | |
| 145 | +| Deciders line | The withdrawal was itself the decision | Reconstructed from the tree in 2026-08; nobody decided the number should retire at the time | |
| 146 | +| Why not resurrect | Substance reversed by later shipped code | Same — the fallback-provider half is contradicted by the code today | |
| 147 | + |
| 148 | +The shared conclusion is the one that matters: an ADR number that has ever named a record |
| 149 | +does not become free again by that record's removal, however the removal happened. |
0 commit comments