Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,21 @@ jobs:
continue-on-error: true
run: pnpm check:adr-anchors

# #26076 ADR index, REPORT-ONLY by the maintainer's ruling (门禁不加).
# docs/adr/README.md is generated by scripts/adr-index.mjs from the
# records' one `**Status**:` line; the alias runs the generator's
# `--self-test` (fixtures only — it never asserts on what the records
# say) and then `--report`, which prints a `::warning::` for a stale
# index or a record whose status line is missing or unreadable and exits
# 0 whatever it finds. So the only red this step can show is a broken
# generator, never a record. `pnpm adr:index` regenerates; `--check` is
# the gate's spelling for the day a maintainer names one. Alias form per
# the GATE INVOCATION IDIOM note at the top of this file.
- name: ADR index is current (report-only — warnings, never a red on a record)
id: adr-index-current-report-only
continue-on-error: true
run: pnpm check:adr-index

# @objectstack/verify stand-in erasure guard (#6399). The third and
# narrowest member of the slot-lookup and query-options erasure ratchets
# (in the scoped lanes since #22991). `checkReadCoercion` /
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0006-project-environment-split.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0006: Environment & Project as Independent Siblings — v3

**Status**: Superseded by v4 (`0006-project-environment-split.v4.md`) — 2026-05-20
**Versions of this number**: [v2](./0006-project-environment-split.v2.md) · [v3](./0006-project-environment-split.md) · [v4, current](./0006-project-environment-split.v4.md) — one decision revised twice; the number is shared only by its own revisions (AGENTS.md Prime Directive 13). A version is cited as `ADR-0006 v4` in prose or, stem-qualified, as `ADR-0006-project-environment-split.v4`.
**Date**: 2026-05-20 (v3)
**Deciders**: ObjectStack Protocol Architects
**Supersedes**: v1 (strict tree), v2 (siblings + sys_deployment join)
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0006-project-environment-split.v2.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0006: Three-Layer Tenancy — Organization, Project, Environment

**Status**: Superseded by v4 (`0006-project-environment-split.v4.md`) — 2026-05-20
**Versions of this number**: [v2](./0006-project-environment-split.v2.md) · [v3](./0006-project-environment-split.md) · [v4, current](./0006-project-environment-split.v4.md) — one decision revised twice; the number is shared only by its own revisions (AGENTS.md Prime Directive 13). A version is cited as `ADR-0006 v4` in prose or, stem-qualified, as `ADR-0006-project-environment-split.v4`.
**Date**: 2026-05-20 (v1) / 2026-05-20 (v2 — same day revision)
**Deciders**: ObjectStack Protocol Architects
**Builds on**: ADR-0002 (Environment-Per-Database Isolation), ADR-0003 (Package as First-Class Citizen), ADR-0005 (Metadata Customization Overlay)
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0006-project-environment-split.v4.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0006: Environment & Project — v4 (drop dev-workspace Project, unify on Package)

**Status**: Accepted (v4 — supersedes v3) — API-surface vocabulary boundary recorded 2026-08-27 (#12473): the v5.0 `project` → `environment` rename stops at the CLI's user-facing vocabulary; three API surfaces keep `project` deliberately (see the addendum). **D1 retired by execution (2026-08-28, #12867 — see the second addendum):** D2 fired on the maintainer's 2026-08-28 ruling; all three of those surfaces are renamed to `environment` / `environments` with no aliases, authored and parked for one coordinated release. Read the first addendum's D1 as history — the boundary it draws no longer exists.
**Versions of this number**: [v2](./0006-project-environment-split.v2.md) · [v3](./0006-project-environment-split.md) · [v4, current](./0006-project-environment-split.v4.md) — one decision revised twice; the number is shared only by its own revisions (AGENTS.md Prime Directive 13). A version is cited as `ADR-0006 v4` in prose or, stem-qualified, as `ADR-0006-project-environment-split.v4`.
**Date**: 2026-05-20 (v4)
**Deciders**: ObjectStack Protocol Architects
**Supersedes**: v1 (strict tree), v2 (siblings + sys_deployment join), v3 (siblings + deferred dev-workspace `sys_project`)
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0009-execution-pinned-metadata.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0009: Execution-Pinned Metadata

**Status:** Accepted
**Status**: Accepted
**Date:** 2026-05-22
**Supersedes:** —
**Builds on:** ADR-0008 (Metadata Repository & Change Log)
Expand Down
3 changes: 2 additions & 1 deletion docs/adr/0010-metadata-protection-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

> **Protocol 18 update (2026-10-12, ADR-0131 C5, #22340):** The per-type overlay opt-in on `MetadataTypeRegistryEntry` is spelled `allowEnvironmentOverlay` from protocol 18 (`packages/spec/src/kernel/metadata-plugin.zod.ts#allowEnvironmentOverlay`). [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) D6 retired the per-organization overlay axis, so the key now names the one scope it governs — whether an environment may overlay an item of this type that a managed package ships. The old key `allowOrgOverride` stays on the registry entry schema only as a tombstone that refuses at parse with the new name in its prescription: no second key, no alias, no conversion. The lines below that name `allowOrgOverride` describe the field as it was spelled when they were written and are preserved verbatim.

**Status:** Proposed
**Status**: Proposed
**Shares its number with**: [`0010-nl-to-flow-authoring`](./0010-nl-to-flow-authoring.md) (Natural-Language → Flow Authoring) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0010-metadata-protection-model`.
**Date:** 2026-05-29
**Supersedes:** —
**Builds on:** ADR-0005 (Metadata Customization Overlay), ADR-0008 (Metadata Repository & Change Log), ADR-0009 (Execution-Pinned Metadata)
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0010-nl-to-flow-authoring.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0010: Natural-Language → Flow Authoring (Platform Capability)

**Status**: Draft (2026-05-24)
**Shares its number with**: [`0010-metadata-protection-model`](./0010-metadata-protection-model.md) (Metadata Protection Model) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0010-nl-to-flow-authoring`.
**Authors**: HotCRM (objectstack-ai/hotcrm) — surfacing requirements from the v1 launch story
**Consumers**: `@objectstack/service-ai`, `@objectstack/spec` (automation), `objectui` (plugin-designer, plugin-chatbot), every app that ships flows

Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0014-record-form-field-type.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0014 — `record` Form Field Type

- **Status:** Accepted
**Status**: Accepted
- **Date:** 2026-04-17
- **Supersedes:** —
- **Related:** ADR-0005 (Metadata Customization Overlay), Prime Directive #1 (Zod First)
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0019-app-as-consumer-unit.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0019: App as the Consumer-Facing Unit

**Status**: Proposed (v3 — narrowed to the consumer-surface decision)
**Shares its number with**: [`0019-approval-as-flow-node`](./0019-approval-as-flow-node.md) (Collapse Approval into Flow — approval as a durable-pause node) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0019-app-as-consumer-unit`.
**Date**: 2026-05-31
**Deciders**: ObjectStack Protocol Architects
**Builds on**: ADR-0003 (Package as First-Class Citizen), ADR-0006 (Three-Layer Tenancy), ADR-0016 (Studio Package Authoring & Publish)
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0019-approval-as-flow-node.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0019: Collapse Approval into Flow — one engine, approval as a durable-pause node

**Status**: Accepted (2026-05-31) — fully implemented (A1–A5)
**Shares its number with**: [`0019-app-as-consumer-unit`](./0019-app-as-consumer-unit.md) (App as the Consumer-Facing Unit) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0019-approval-as-flow-node`.
**Deciders**: ObjectStack Protocol Architects
**Builds on**: [ADR-0018](./0018-unified-node-action-registry.md) (open action registry — approval becomes a consumer), [ADR-0009](./0009-execution-pinned-metadata.md) (execution pinning — reconcile to one mechanism), [ADR-0012](./0012-notification-platform.md) (outbox / `notify`), [ADR-0010](./0010-nl-to-flow-authoring.md) + [ADR-0011](./0011-actions-as-ai-tools.md) (AI authoring — the design center)
**Revises**: ADR-0018's premise that Approval stays a separate paradigm with its own closed `ApprovalActionType` enum, and the "Workflow-Rule → Flow compiler" (M5) — both dropped here (greenfield, no legacy).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0057: ERP-Grade Authorization Core — Business-Unit Partitioning, Scope-Depth Grants, and Hierarchy Rollup

**Status**: Accepted in part (2026-06-21) — D1–D3/D8 implemented (scope-depth enum + evaluator, `sys_business_unit` tree, hierarchy-resolver seam, conformance rows); **D4–D7 superseded by ADR-0090 D3 / ADR-0095**: the `sys_role`/`sys_user_role`/`role_and_subordinates` vocabulary never shipped — the code realizes them as flat `sys_position`/`sys_user_position` with rollup on the BU tree. This ADR's own implementation-status table predates that supersession; read it with the rename applied. · **Amended** (2026-10-14, [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) D3/D13): the flat `sys_position` row object named above is itself retired by #15204 stage 8 (`66949b7729`, 2026-10-13), and its `sys-position.object.ts`, which the path note below names, is deleted; a position is a metadata-registry definition, and the `sys_user_position` assignment stays.
**Shares its number with**: [`0057-system-data-lifecycle-and-retention`](./0057-system-data-lifecycle-and-retention.md) (System data has a lifecycle — declarative retention, rotation, and reclamation) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0057-erp-authorization-core-business-units-and-scope-depth`.
**Deciders**: ObjectStack Protocol Architects
**Path note (2026-09), paths only — no decision changes**: this record cites the **pre-rename**
vocabulary, and those four paths no longer resolve. `sys-department.object.ts` and `department-graph.ts`
Expand Down
1 change: 1 addition & 0 deletions docs/adr/0057-system-data-lifecycle-and-retention.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ADR-0057: System data has a lifecycle — declarative retention, rotation, and reclamation for platform-generated objects

**Status**: Accepted — **P0–P4 implemented** (P0 shipped with this ADR, [#2079](https://github.com/objectstack-ai/objectstack/pull/2079); P1–P4 in [#2791](https://github.com/objectstack-ai/objectstack/pull/2791), tracked in [#2786](https://github.com/objectstack-ai/objectstack/issues/2786)) (proposed 2026-06-20 · implemented 2026-07-10)
**Shares its number with**: [`0057-erp-authorization-core-business-units-and-scope-depth`](./0057-erp-authorization-core-business-units-and-scope-depth.md) (ERP-Grade Authorization Core — business-unit partitioning, scope-depth grants, hierarchy rollup) — an unrelated decision under the same number. Numbers are never reassigned (AGENTS.md Prime Directive 13); cite this record unambiguously as `ADR-0057-system-data-lifecycle-and-retention`.
**Deciders**: ObjectStack Protocol Architects
**Builds on**: [ADR-0052](./0052-audit-is-not-the-activity-feed.md) (decomposed audit / activity / collaboration into bounded contexts — this ADR adds the *orthogonal* axis those contexts never specified: **how long each one lives and how its space is reclaimed**), [ADR-0049](./0049-no-unenforced-security-properties.md) (enforce-or-remove — a declared `retention` that drives no sweeper is dead surface; this ADR wires it to a runtime consumer), [ADR-0030](./0030-notification-platform-convergence.md) (notification objects are messaging-owned with their own lifecycle), [ADR-0021](./0021-analytics-dataset-semantic-layer.md) (precedent for moving event-shaped data off the primary OLTP store)
**Consumers**: `@objectstack/spec` (`lifecycle` object property + `LifecycleClass`), `@objectstack/objectql` (LifecycleService: Reaper / Rotator / Archiver), `@objectstack/plugin-audit` (audit/activity exclusion of telemetry objects — shipped P0), `@objectstack/driver-sql` (`auto_vacuum=INCREMENTAL` default + incremental-vacuum hook — shipped P0), `@objectstack/dogfood` (storage-growth regression gate), platform spec-liveness gate
Expand Down
6 changes: 1 addition & 5 deletions docs/adr/0071-dataset-semantic-layer-depth.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ADR-0071: Dataset semantic-layer depth — multi-hop joins

## Status

Proposed. (Refocused — see **Correction** below. The first merged draft also
proposed matrix/across pivoting; a code check found that already implemented, so
this ADR now covers only the remaining gap: multi-hop joins.) **Multi-hop to-one joins (≤3 hops / 4 objects) have since been implemented & are live — header pending formal update.**
**Status**: Proposed. (Refocused — see **Correction** below. The first merged draft also proposed matrix/across pivoting; a code check found that already implemented, so this ADR now covers only the remaining gap: multi-hop joins.) **Multi-hop to-one joins (≤3 hops / 4 objects) have since been implemented & are live — header pending formal update.**

## Correction (2026-06-24)

Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0079-record-display-name.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0079: The record display-name contract — `nameField` is the one canonical primary-title pointer

- **Status**: Accepted — implemented. **This file is a RETROACTIVE RECONSTRUCTION written 2026-08-08**, not a contemporaneous record; see [Provenance](#provenance-read-this-before-citing-this-file) before you cite it.
**Status**: Accepted — implemented. **This file is a RETROACTIVE RECONSTRUCTION written 2026-08-08**, not a contemporaneous record; see [Provenance](#provenance-read-this-before-citing-this-file) before you cite it.
- **Decided**: 2026-06-28 (the decision), reconstructed 2026-08-08 (this file)
- **Reconstructed by**: #6634
- **Implemented by**: [#2434](https://github.com/objectstack-ai/objectstack/pull/2434) (foundation — `nameField` + resolver), [#2458](https://github.com/objectstack-ai/objectstack/pull/2458) (designate-only provisioning at the registry seam), [#2463](https://github.com/objectstack-ai/objectstack/pull/2463) (the author-time gate)
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0091-grant-lifecycle-and-recertification.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0091: Grant lifecycle — effective-dated assignments, delegation, break-glass, recertification substrate

- **Status:** Accepted
**Status**: Accepted
· **Amended** (2026-10-14, [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) D3/D13): `sys_position_permission_set`, which D1 and the non-goals leave undated, and the `sys_position` row L2 adds `delegatable` to, are retired by #15204 stage 8 (`66949b7729`, 2026-10-13); a position's sets and its `delegatable` flag are its metadata-registry definition. D1's dated assignment rows stand.
- **Date:** 2026-07-09 (proposed) · 2026-07-10 (accepted)
- **Deciders:** jack@objectstack.ai
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0092-sys-user-profile-field-delegation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0092: Identity-table write guard — engine-enforced `managedBy: 'better-auth'`, with sys_user profile fields as the first whitelist

- **Status:** Accepted
**Status**: Accepted
- **Date:** 2026-07-10 (proposed) · 2026-07-11 (revised: D2 generalized from a sys_user-only hook to a registry-driven guard over every better-auth-managed object, per review) · 2026-07-11 (accepted) · **2026-09-03 (amended: D5 — self-service edits of the whitelisted columns route through the generic data path; see the D5 Amendment)** · **2026-09-05 (amended: D1 — Tier 1 becomes `{name, image, locale}`, carrying the 2026-09-03 ruling on #14787; see the D1 Amendment)**
- **Implementation:** #2816 (generic identity write guard — D2/D3/D6) → #2817 (sys_user edit affordance + form field gating — D4, gated on #2816)
- **Deciders:** ObjectStack Protocol Architects
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0093-tenancy-mode-and-membership-lifecycle.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0093: Tenancy mode as a first-class capability, and a single owner for the user→membership lifecycle

- **Status:** Accepted (2026-07-13) — implemented: `tenancy` kernel service (`plugin-auth/src/tenancy-service.ts`), membership reconciler (`reconcile-membership.ts`), locked by `dogfood/test/membership-reconciler.dogfood.test.ts`
**Status**: Accepted (2026-07-13) — implemented: `tenancy` kernel service (`plugin-auth/src/tenancy-service.ts`), membership reconciler (`reconcile-membership.ts`), locked by `dogfood/test/membership-reconciler.dogfood.test.ts`
- **Date:** 2026-07-13
- **Deciders:** ObjectStack Protocol Architects
- **Implementation:** #2882 (Phase 0 — tactical create-user bind, merged) → this PR (Phases 1–3 — `tenancy` service, fail-fast boot guard, membership reconciler, consumer migration, backfill, docs). One revision from the original plan, ratified in D2: the endpoint-level create-user bind **delegates to the shared reconciler** (one implementation, two call sites) instead of being deleted. Runtime verification confirmed the hook fires for `admin.createUser`, but better-auth *defers* `user.create.after` post-commit (#1881), so the endpoint keeps its delegated call to report `organizationId` / `membershipCreated` deterministically in its response. Cloud-host semantics (personal-org hook precedence, multi-org non-binding, D5 blast radius) verified against `objectstack-ai/cloud` — see D2/D3/D5.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0098-pinyin-search-companion-column.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0098: Pinyin Search via a Locale-Gated Companion Column

- **Status**: Accepted
**Status**: Accepted
- **Date**: 2026-07-16
- **Issue**: #2486
- **Extends**: ADR-0061 (record search architecture — purely additive), ADR-0045 (additive materialization), ADR-0079 (display-name contract)
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0100-credential-field-channels.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0100: Credential Field Channels — `secret` (encrypted) and `password` (masked)

- **Status**: Accepted
**Status**: Accepted
- **Date**: 2026-07-18
- **Issue**: #2036 (found via #2033 / #2025 / #2028 field-type round-trip work)
- **Relates to**: ADR-0077 (authoring-surface boundary), ADR-0078 (no silently
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0103: `managedBy` write policy — split the overloaded `system` bucket, enforce engine-owned writes

- **Status**: Accepted (D5 completed in v17 — see the #3355 addendum at the end:
**Status**: Accepted (D5 completed in v17 — see the #3355 addendum at the end:
the residual `system` bucket is renamed `system-data` and the bare value retired)
· **Amended** (2026-10-14, [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) D3/D13): `sys_position_permission_set`, one of the RBAC link tables this record files as writable data, and `sys_position` / `sys_capability`, two of the provenance-column objects it sets apart, are retired as row objects by #15204 stage 8 (`66949b7729`, 2026-10-13); the policy stands. See the notes in the Context and the two addenda.
- **Date**: 2026-07-19
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0104-field-runtime-value-shape-contract.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0104: Field runtime value-shape as a first-class contract — spec-owned value schemas, typed action handlers, file-as-reference

- **Status**: Accepted (2026-07-22) — staged per D4. D1 landed (#3429), D2
**Status**: Accepted (2026-07-22) — staged per D4. D1 landed (#3429), D2
landed (#3432); D3 refined into two waves by the 2026-07-24 addendum below,
and wave 2's ownership model settled by the 2026-07-27 addendum.
Strict-default flip of D1/D2 tracked in #3438 — the media half flips per
Expand Down
4 changes: 2 additions & 2 deletions docs/adr/0110-action-identity-and-declaration-admission.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ ones); the engine-side aliasing alternative (deferred); any change to how
before the refusal exists.
3. **D3/D6** — refusal ON by default with no opt-out, plus the `v17.mdx`
migration entry. Same PR flips this
ADR to `Accepted — implemented` with evidence (the PRIORITIZATION
status-hygiene rule).
ADR to `Accepted — implemented` with evidence (the status-hygiene rule,
kept in `docs/adr/README.md`).

Steps 1→3 may land in separate PRs but **must not ship in separate
releases**: step 3 without step 1 refuses correctly-declared actions.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/0117-owning-business-unit-record-stamp.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR-0117: 记录级业务单元归属(owning business unit)

- **状态**: **Accepted (D1/D3 scoped)**(2026-08-05)—— 仅 **D1**(`ownership` 新增
**Status**: **Accepted (D1/D3 scoped)**(2026-08-05)—— 仅 **D1**(`ownership` 新增
`business_unit` 一档与 `owning_business_unit_id` 记录戳的命名与语义)与 **D3**
(`record.organization_id == sys_business_unit(owning_business_unit_id).organization_id`
不变量)进入协议。**D5、D2 的默认盖章策略、D8 的启用门粒度、D4 的权限位选择仍为
Expand Down
Loading
Loading