@reventlessdev/reventless-spec 3.0.0-alpha.116 → 3.0.0-alpha.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.117 (2026-08-18)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **api:** declare the reference door in the SDL every backend is built from ([5c1857e](https://github.com/ReventlessDev/reventless-core/commit/5c1857ea90ff40305a1c44a9e57043528e6a93aa))
11
+ ### Features
12
+
13
+ * **core:** let a reference name a retired row, and let an elevated caller open one ([9e2623a](https://github.com/ReventlessDev/reventless-core/commit/9e2623a4b22487561607fcc0ca19d51726069ee4))
14
+
15
+
6
16
  # 3.0.0-alpha.116 (2026-08-16)
7
17
 
8
18
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-spec",
3
- "version": "3.0.0-alpha.116",
3
+ "version": "3.0.0-alpha.117",
4
4
  "description": "Specifications for Reventless",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "sury": "11.0.0-alpha.4",
22
22
  "sury-ppx": "11.0.0-alpha.2",
23
23
  "yaml": "^2.8.3",
24
- "@reventlessdev/rescript-node": "2.0.0-alpha.7"
24
+ "@reventlessdev/rescript-node": "2.0.0-alpha.8"
25
25
  },
26
26
  "devDependencies": {
27
27
  "rescript": "12.3.0",
@@ -178,6 +178,13 @@ enum Platform_PluginKind {
178
178
  PlatformInfrastructure
179
179
  }
180
180
 
181
+ type Platform_PluginRef {
182
+ id: ID!
183
+ label: String!
184
+ retired: Boolean!
185
+ retiredState: String
186
+ }
187
+
181
188
  enum Platform_PluginStatus {
182
189
  Connected
183
190
  Disconnected
@@ -215,6 +222,7 @@ type Platform_ReadSideDef {
215
222
  lifecycleField: String
216
223
  linkedWriteSide: [String!]!
217
224
  name: String!
225
+ namedWhenRetired: Boolean!
218
226
  ownerField: String
219
227
  queryField: String!
220
228
  requiredAccess: [String!]
@@ -290,10 +298,11 @@ type PluginStatusChangeEvent {
290
298
 
291
299
  type Query {
292
300
  Platform_ComponentDefinitions: [Platform_ComponentDefinitionEntry!]!
293
- Platform_Plugin(id: ID!): Platform_Plugin
301
+ Platform_Plugin(id: ID!, includeRetired: Boolean): Platform_Plugin
294
302
  Platform_PluginStructures: [Platform_PluginStructureEntry!]!
295
303
  Platform_Plugins(after: String, before: String, filter: Platform_PluginFilter, first: Int, includeRetired: Boolean, last: Int): Platform_PluginConnection!
296
- Platform_PluginsByIds(ids: [String!]!): [Platform_Plugin!]!
304
+ Platform_PluginsByIds(ids: [String!]!, includeRetired: Boolean): [Platform_Plugin!]!
305
+ Platform_PluginsRefs(ids: [ID!]!): [Platform_PluginRef!]!
297
306
  Platform_UIFragments: [Platform_UIFragmentEntry!]!
298
307
  }
299
308
 
@@ -325,6 +325,26 @@ type queryableDef = {
325
325
  */
326
326
  retiredValues: @s.matches(stringArrayOptionSchema) option<array<string>>,
327
327
  /**
328
+ Whether this view publishes a **reference door**: the by-ids read that names a
329
+ retired row for any caller holding a pointer to it, projected to the row's id,
330
+ its `labelField` and the value of `retiredField`. Declared with
331
+ `@namedWhenRetired` on the state record.
332
+
333
+ Published so a client knows the door exists without probing for it — a query
334
+ against a field the schema does not have is a validation error, not an empty
335
+ answer, so "ask and see" is not a usable fallback here.
336
+
337
+ Nullable rather than a bare required bool, which is the rule this schema's own
338
+ tripwire enforces: a definition stored before the field existed would otherwise
339
+ decode with an invented value and a runtime warning. Absent and `false` mean the
340
+ same thing to every reader — the archive stays shut — but only one of them is
341
+ something the platform actually said.
342
+
343
+ It is never `true` without `retiredField`: the PPX refuses the annotation on a
344
+ record with no retirement.
345
+ */
346
+ namedWhenRetired: @s.matches(boolOptionSchema) option<bool>,
347
+ /**
328
348
  Component visibility hint (`@@reventless.visibility`). `Some("Internal")` marks a
329
349
  ReadModel / StateViewSlice that the deployed AutoUI hides from its menu, drill-down
330
350
  pages, web event graph and cross-plugin edges. `None` (absent) means Public. Internal
@@ -122,6 +122,7 @@ let queryableDefSchema = S.schema(s => ({
122
122
  ownerField: s.m(stringOptionSchema),
123
123
  retiredField: s.m(stringOptionSchema),
124
124
  retiredValues: s.m(stringArrayOptionSchema),
125
+ namedWhenRetired: s.m(boolOptionSchema),
125
126
  visibility: s.m(stringOptionSchema),
126
127
  chapter: s.m(stringOptionSchema),
127
128
  singleQueryField: s.m(stringOptionSchema),
@@ -81,6 +81,27 @@ type retiredSpec = {
81
81
  most visibly — would stop firing on a value that looks merely empty.
82
82
  */
83
83
  values: option<array<string>>,
84
+ /**
85
+ Whether a reference to a retired row of this record still resolves — the
86
+ `@namedWhenRetired` opt-in on the `@schema type state` declaration.
87
+
88
+ Retirement withholds a row from every door at once, which is the right answer
89
+ to "what may this caller browse" and an unasked answer to "what is the row this
90
+ caller is already holding a reference to called". An order names a product it
91
+ bought; archiving the product should not unname it on the order.
92
+
93
+ `true` opens exactly one door: a retired row answers a by-ids reference read
94
+ with its id, its label field and the value of `field` — and nothing else, for
95
+ any caller. It does not widen the list, the single-entity read, the index reads
96
+ or the live frame, and it does not touch the owner rule: a retired row that is
97
+ owner-scoped still resolves for its owner alone.
98
+
99
+ Inside `retiredSpec` rather than beside it, because it is a rule about withheld
100
+ rows and there are none without a retirement — the PPX errors on the annotation
101
+ when the record declares no `@retired`, so the nesting states a guarantee rather
102
+ than a convention.
103
+ */
104
+ namedWhenRetired: bool,
84
105
  }
85
106
 
86
107
  type stateAnnotationSpec = {