|
5 | 5 | **Builds on**: [ADR-0003](./0003-package-as-first-class-citizen.md) (package as first-class citizen), [ADR-0005](./0005-metadata-customization-overlay.md) (artifact vs runtime overlay precedence), [ADR-0008](./0008-metadata-repository-and-change-log.md) (metadata repository, `MetaRef` identity), [ADR-0010](./0010-metadata-protection-model.md) (package provenance / `_packageId` stamping) |
6 | 6 | **Consumers**: `@objectstack/objectql` (`SchemaRegistry.registerItem`, `ObjectQL.registerApp`, install path), `@objectstack/console` / `objectui` (routing + metadata resolution), package authors, CLI/CI install path, the app marketplace registry. |
7 | 7 | **Surfaced by**: ADR-0046 review (doc naming) → generalised to all bare-named metadata → re-examined through the app-marketplace install lens. |
8 | | -**Addenda**: [2026-08-08 — publish-time / marketplace namespace exclusivity](#addendum-2026-08-08-publish-time--marketplace-namespace-exclusivity) (**Accepted** 2026-08-08 — maintainer ruling on #1825, [acceptance comment 5226411687](https://github.com/objectstack-ai/objectstack/issues/1825#issuecomment-5226411687), landed by PR #6671; additive to §3.2, supersedes nothing); [2026-11-06 — bare names resolved without a package hold one package](#addendum-2026-11-06-bare-names-resolved-without-a-package-hold-one-package--34-narrowed) (**Accepted**, ruling C on #30798, phase 1; narrows §3.4 for picklists, mappings, datasets, APIs, object-less actions and engine functions, supersedes nothing). |
| 8 | +**Addenda**: [2026-08-08 — publish-time / marketplace namespace exclusivity](#addendum-2026-08-08-publish-time--marketplace-namespace-exclusivity) (**Accepted** 2026-08-08 — maintainer ruling on #1825, [acceptance comment 5226411687](https://github.com/objectstack-ai/objectstack/issues/1825#issuecomment-5226411687), landed by PR #6671; additive to §3.2, supersedes nothing); [2026-11-06 — bare names resolved without a package hold one package](#addendum-2026-11-06-bare-names-resolved-without-a-package-hold-one-package--34-narrowed) (**Accepted**, ruling C on #30798, phase 1; narrows §3.4 for picklists, mappings, datasets, APIs, object-less actions, engine functions, flows, webhooks, connectors and email templates, supersedes nothing). |
9 | 9 |
|
10 | 10 | --- |
11 | 11 |
|
@@ -267,22 +267,28 @@ package — stays covered by the `naming/namespace-prefix` lint in `os lint`. |
267 | 267 | > [Addendum (2026-10-08)](#addendum-2026-10-08-the-security-catalog-holds-one-name-per-deployment--34-narrowed). |
268 | 268 |
|
269 | 269 | > **Narrowed (2026-11-06) — picklists, mappings, datasets, APIs, object-less |
270 | | -> actions and engine functions are out of §3.4.** Their consumers resolve the |
271 | | -> name with no package — a field's `picklist`, an import's `mappingName`, a |
272 | | -> dashboard's `datasetName`, the endpoint matcher's one API per name, |
273 | | -> `/actions/global/NAME`, a flow `script` node's function — so with two holders |
274 | | -> every caller is served one of them, chosen by registration order, measured on a |
275 | | -> booted two-package deployment (#30803). Once the cold boot has sealed the |
276 | | -> registry, a package whose picklist, mapping, dataset, API or object-less action |
277 | | -> bears a name another installed package holds is refused at managed install and |
278 | | -> at package registration (a built-in's name, at managed install), and a package |
279 | | -> whose handlers bring a function another package holds is refused at the hook |
280 | | -> binder's bind, each naming both holders and the rename. ⛔ The environment |
281 | | -> catalog is never a holder: an environment item under a package's name is the |
282 | | -> ADR-0005 overlay. The other types the measurement found resolving without a |
283 | | -> package context — `email_template`, `webhook`, `connector`, `flow`, `agent` and |
284 | | -> `skill` — are to follow, each family in its own change. Every other type, |
285 | | -> an action bound to an object among them, keeps §3.4 as written. See |
| 270 | +> actions, engine functions, flows, webhooks, connectors and email templates are |
| 271 | +> out of §3.4.** Their consumers resolve the name with no package — a field's |
| 272 | +> `picklist`, an import's `mappingName`, a dashboard's `datasetName`, the |
| 273 | +> endpoint matcher's one API per name, `/actions/global/NAME`, a flow `script` |
| 274 | +> node's function, the automation engine's one armed flow per name, the |
| 275 | +> dispatcher's one declared webhook per name, the connector picker's one |
| 276 | +> connector per name, a send's `template` — so with two holders every caller is |
| 277 | +> served one of them, chosen by registration order, measured on a booted |
| 278 | +> two-package deployment (#30803). Once the cold boot has sealed the registry, a |
| 279 | +> package whose picklist, mapping, dataset, API, object-less action, flow, |
| 280 | +> webhook, connector or email template bears a name another installed package |
| 281 | +> holds is refused at managed install and at package registration (a built-in's |
| 282 | +> name, at managed install), and a package whose handlers bring a function |
| 283 | +> another package holds is refused at the hook binder's bind, each naming both |
| 284 | +> holders and the rename. ⛔ The environment catalog is never a holder: an |
| 285 | +> environment item under a package's name is the ADR-0005 overlay. ⛔ Nor is the |
| 286 | +> email service's built-in template bundle: an app's same-named template |
| 287 | +> overrides it by contract (ADR-0131 D6), so that package holds no template name |
| 288 | +> and is refused none. The remaining types the measurement found resolving |
| 289 | +> without a package context — `agent` and `skill` — are to follow in the series' |
| 290 | +> last change. Every other type, an action bound to an object among them, keeps |
| 291 | +> §3.4 as written. See |
286 | 292 | > [Addendum (2026-11-06)](#addendum-2026-11-06-bare-names-resolved-without-a-package-hold-one-package--34-narrowed). |
287 | 293 |
|
288 | 294 | ### 3.5 Namespace rename-on-install is deferred (non-goal) |
@@ -950,8 +956,8 @@ first phase. |
950 | 956 |
|
951 | 957 | > **Status of this addendum: Accepted** — it records phase 1 of a maintainer |
952 | 958 | > ruling. It **narrows §3.4 for more metadata types, one family per change (P1.2, |
953 | | -> P1.7), and supersedes no other text**: §§1–6, the 2026-08-08 addendum and the |
954 | | -> 2026-10-08 addendum stand verbatim. |
| 959 | +> P1.7, P1.8), and supersedes no other text**: §§1–6, the 2026-08-08 addendum and |
| 960 | +> the 2026-10-08 addendum stand verbatim. |
955 | 961 | > |
956 | 962 | > **Ruling this addendum records** — #30798, answered by the maintainer |
957 | 963 | > 「同意 c」 (ruling record 6676670839, 2026-11-06). The ruled option's text, |
@@ -1059,18 +1065,17 @@ the doors never refuse. |
1059 | 1065 |
|
1060 | 1066 | ### P1.5 To follow |
1061 | 1067 |
|
1062 | | -The same measurement found these types resolving without a package context too: |
1063 | | -`email_template`, `webhook` (the second package's webhook is never subscribed), |
1064 | | -`connector`, `flow`, `agent` and `skill`. Each family joins P1.2's list in its own |
1065 | | -change under #30803 — `flow`, `webhook`, `connector` and `email_template`; then |
1066 | | -`agent` and `skill` — with its own pins, narrowing §3.4 the same way (the |
1067 | | -maintainer kept all of them in #30803 on 2026-11-06). `tool` and `rag_pipeline` |
1068 | | -share a reader with `agent` and were not measured. The request family that was |
1069 | | -listed here is P1.7. |
| 1068 | +The same measurement found `agent` and `skill` resolving without a package |
| 1069 | +context too. They join P1.2's list in the series' last change under #30803, with |
| 1070 | +their own pins, narrowing §3.4 the same way (the maintainer kept all of them in |
| 1071 | +#30803 on 2026-11-06). `tool` and `rag_pipeline` share a reader with `agent` and |
| 1072 | +were not measured. The request family that was listed here is P1.7; the flow |
| 1073 | +family — `flow`, `webhook`, `connector` and `email_template` — is P1.8. |
1070 | 1074 |
|
1071 | 1075 | ### P1.6 Where it is implemented |
1072 | 1076 |
|
1073 | | -`@objectstack/objectql`: the rule, the holders and the switch in |
| 1077 | +`@objectstack/objectql`: the rule, the holders, the overridable baseline |
| 1078 | +(`OVERRIDABLE_BASELINE_PACKAGES`, P1.8) and the switch in |
1074 | 1079 | `bare-name-one-holder.ts`; the package door in `SchemaRegistry.installPackage` and |
1075 | 1080 | the item seam in `SchemaRegistry.registerItem`; the function door in |
1076 | 1081 | `bindHooksToEngine`, through `SchemaRegistry.claimBareNameFunctions`; the seal in |
@@ -1115,3 +1120,61 @@ ambiguous: the binder resolves it among its own package's functions only. |
1115 | 1120 | **The cold boot** reads the bind claims with the registry's holders, under P1.3's |
1116 | 1121 | switch: two packages of one boot binding one function name are named in the same |
1117 | 1122 | warning line, as packages, never as their handler owners. |
| 1123 | + |
| 1124 | +### P1.8 The flow family: `flow`, `webhook`, `connector`, `email_template` |
| 1125 | + |
| 1126 | +Measured with P1.1's two packages, in both orders (#30803, PR 3): |
| 1127 | + |
| 1128 | +- **`flow`** — the automation engine keys its flow map by the bare name and |
| 1129 | + arms ONE flow per name: the lexicographically-first package's |
| 1130 | + (`resolveFlowPrecedence`), whichever registered first, with a warning naming |
| 1131 | + both — the one type of the nine that warns; `/meta/flow/NAME` serves the |
| 1132 | + FIRST-registered package's declaration, so in one order the body the designer |
| 1133 | + opens and the body that runs come from two packages. A third package installed |
| 1134 | + after the boot under that name installs (`200`) and is shadowed. |
| 1135 | +- **`webhook`** — the dispatcher's declared-webhook reader keeps the |
| 1136 | + FIRST-registered package's declaration per name and never subscribes the |
| 1137 | + other, silently; `/meta/webhook/NAME` serves the same one. |
| 1138 | +- **`connector`** — `/meta/connector/NAME` (the by-name door the designer's |
| 1139 | + connector picker reads) serves the FIRST-registered package's descriptor, |
| 1140 | + silently. Two provider-bound instances under one name at boot are already |
| 1141 | + refused by the automation service (ADR-0097's duplicate, fatal at boot); after |
| 1142 | + the boot the second is logged at `error` and skipped, its install answering |
| 1143 | + `200`. |
| 1144 | +- **`email_template`** — a send's `template: NAME` resolves the |
| 1145 | + FIRST-registered package's bundle, silently; `/meta/email_template/NAME` serves |
| 1146 | + the same one. |
| 1147 | + |
| 1148 | +**What is refused.** All four join P1.2's list: the same two doors, the same |
| 1149 | +holders, the same envelope and rename. A provider-bound connector instance and a |
| 1150 | +catalog descriptor hold the name alike — it is the connector's identity in the |
| 1151 | +engine's registry and the picker both. An email template's NAME holds its |
| 1152 | +bundle: the registry keys the type by `(name, locale)` (`pkg:name@locale`), the |
| 1153 | +holder reading strips the member, two members of one package's bundle are one |
| 1154 | +holder, and another package's member of that name — another locale included — is |
| 1155 | +one conflict, on the name. |
| 1156 | + |
| 1157 | +**The overridable baseline.** The platform's built-in auth templates are |
| 1158 | +code-declared under the email service's own package |
| 1159 | +(`EmailServicePlugin.init`, `@objectstack/plugin-email`), and the template loader |
| 1160 | +serves any OTHER package's `(name, locale)` member over them by contract |
| 1161 | +(ADR-0131 D6/D10: an app declaring `auth.password_reset` overrides the |
| 1162 | +platform's copy). So that package is an overridable baseline for |
| 1163 | +`email_template` (`OVERRIDABLE_BASELINE_PACKAGES`): it neither holds a template |
| 1164 | +name nor is refused one, at the package door, the item seam and the cold boot |
| 1165 | +alike. The first other package to take a built-in name holds it; a second is |
| 1166 | +refused naming the first, never the baseline. No other type has a baseline today. |
| 1167 | + |
| 1168 | +**Not judged.** A paired `.custom` package's declared override of a base |
| 1169 | +package's flow (ADR-0146 D9 item 1) is a stored row bound to its pair, hydrated |
| 1170 | +into the bare slot — the environment catalog, never a package holder, so the |
| 1171 | +override path stays open. The automation service's own duplicate refusal of two |
| 1172 | +provider-bound instances in ONE boot (ADR-0097) runs before the seal and stands; |
| 1173 | +the doors here judge the install that follows a boot. The kernel `metadata` |
| 1174 | +service's `(type, name)` overwrite is not a consumer of these four on a |
| 1175 | +composed runtime (the webhook reader falls back to it only with no registry), |
| 1176 | +and is not judged. |
| 1177 | + |
| 1178 | +**The cold boot** reads the four with the registry's other holders, under |
| 1179 | +P1.3's switch: the flow precedence warning keeps naming both packages and arming |
| 1180 | +one, as before; the bare-name warning names every clash once with its rename. |
0 commit comments