ReviewOS

also looking at this

stacks/rfcs

RFC 0006: classify every SHOULD and MAY in Protocol 1.0 Part I

#7
Open chris wants to merge rfc-0006-should-and-may into main
1 file +174 -0
rfcs/0006-should-and-may-statements.mdadded+174-0
Changes to rfcs/0006-should-and-may-statements.md
@@ -0,0 +1,174 @@
1---
2number: "0006"
3title: Classify every SHOULD and MAY statement in Protocol 1.0 Part I
4status: Draft
5authors:
6 - chrisbbreuer
7sponsor: unassigned
8created: 2026-10-07
9review-start: null
10review-end: null
11decision-date: null
12protocol-version: "1.0-draft"
13requires:
14 - "0002"
15 - "0004"
16supersedes: []
17superseded-by: []
18implementation-issues:
19 - https://github.com/stacksjs/stacks/issues/2050
20---
21
22# Summary
23
24Every SHOULD, SHOULD NOT and MAY in Part I of the whitepaper becomes either a
25catalog requirement with a stable ID or an entry in a new `informative` list,
26each with a written reason. Six become SHOULD requirements, one is raised to
27the MUST that RFC 0004's report schema already enforces, and sixteen are
28recorded as informative. A SHOULD result is reported but never gates a profile.
29
30# Motivation
31
32Catalog revision 1 carries 47 requirements, all MUST or MUST NOT. Part I uses
33the RFC 2119 keywords 90 times: 55 MUST, 12 MUST NOT, 10 SHOULD, 1 SHOULD NOT
34and 12 MAY (white-paper `bun run normative`, which counts every keyword on a
35line since white-paper 086a4bf; it previously counted only the first and
36reported 65 uses and no SHOULD NOT). The 23 SHOULD/SHOULD NOT/MAY uses are
37neither catalogued nor marked informative, so the first acceptance criterion of
38stacksjs/stacks#2050 - "every normative statement is mapped to a stable ID or
39made informative" - cannot be met, and two conforming implementations can read
40the same SHOULD differently.
41
42One of them also contradicts the machine contract: Part I §16 says reports
43SHOULD link to CI logs and the exact suite revision, while RFC 0004's report
44schema already requires `execution.ci.runUrl`, `protocol.suiteVersion` and
45`protocol.rfcsRevision`.
46
47# Normative specification
48
49## Result semantics for SHOULD
50
51A SHOULD or SHOULD NOT requirement is run and reported like any other, with the
52same `pass`, `fail`, `skipped`, `unsupported`, `exception` and `experimental`
53results. Its result never gates a profile claim: a profile is satisfied by its
54MUST and MUST NOT requirements alone. A report MUST still list every SHOULD
55requirement of the claimed profile with its result, so an unmet
56recommendation is visible rather than absent. `unsupported` is the expected
57result for a statically-typed-host SHOULD in a dynamic host, with its reason.
58
59## New requirements
60
61| ID | Profile | Level | Area | Evidence | Statement | Part I |
62| --- | --- | --- | --- | --- | --- | --- |
63| `CORE-ROUTE-03` | Core | SHOULD | routing | behavior | Resource-route expansion and route parameter constraints are supported. | §4.1, line 412 |
64| `STD-GEN-01` | Standard | SHOULD | generation | inspection | A typed or schema-bearing Model definition drives at least one related artifact: migrations, validation, types, or an API description. | §2.2, line 290 |
65| `STD-TYPE-02` | Standard | SHOULD | types | inspection | In a statically typed host, a validation schema exposes an inferred type. | §4.3, line 448 |
66| `STD-TYPE-03` | Standard | SHOULD | types | inspection | In a statically typed host, configuration is checked against declared types. | §4.5, line 475 |
67| `STD-API-02` | Standard | SHOULD | api | behavior | A machine-readable description such as OpenAPI is generated from registered routes and schemas. | §4.8, line 516 |
68| `STD-QUEUE-02` | Standard | SHOULD | queue | behavior | Delayed dispatch and recurring schedules are supported. | §5.1, line 524 |
69
70`STD-API-02` sits below `COMP-API-01`, which already requires a generated
71description, when there is one, to be fresh and non-placeholder at Complete.
72Standard recommends generating one; Complete requires what is generated to be
73real.
74
75## Raised to MUST
76
77| ID | Profile | Level | Area | Evidence | Statement | Part I |
78| --- | --- | --- | --- | --- | --- | --- |
79| `CORE-REPORT-01` | Core | MUST | reporting | inspection | A conformance report links its CI run and names the exact suite and RFC revisions it ran. | §16, line 1412 |
80
81This adds no obligation: RFC 0004's schema already rejects a report without
82those fields. The prose is aligned with the schema, and §16's bullet changes
83from SHOULD to MUST. A `reporting` source section pointing at §16 is added to
84`sourceSections`.
85
86## Informative
87
88Each is recorded in a new `informative` array in the catalog, with the Part I
89line, the keyword, and the reason. Where a statement carries a condition, the
90condition's requirement is named, so the permission is informative and the
91constraint is not.
92
93| Part I | Keyword | Statement | Why informative |
94| --- | --- | --- | --- |
95| §2.1, line 259 | MAY | A Model MAY declare capabilities such as generated CRUD routes, search indexing, ... | Defines what a Model can contain; constrains nothing. |
96| §2.1, line 265 | MAY | A View MAY contain presentation logic | Defines what a View can contain. |
97| §2.1, line 265 | SHOULD NOT | A View SHOULD NOT own authorization, persistence, or multi-step business rules | Architecture guidance an outside observer cannot test. Its observable part, that rendering preserves authorization boundaries, is `COMP-VIEW-01`. |
98| §2.1, line 271 | MAY | An implementation MAY support inline handlers and controllers | A permission. |
99| §2.1, line 271 | SHOULD | Behavior reused across transports SHOULD live in an Action | Placement guidance; the observable part is `CORE-MVA-01`. |
100| §3.1, line 329 | MAY | Language-idiomatic casing or extensions MAY be used | A permission; the documented mapping it requires is `CORE-CONV-01`. |
101| §3.1, line 353 | MAY | Controllers, resources, policies, broadcasts and notifications MAY be additional roles | Defines optional roles. |
102| §3.3, line 368 | MAY | An implementation MAY ship default application behavior | A permission; the precedence it requires is `CORE-CONV-02`. |
103| §3.4, line 389 | MAY | Defaults MAY be overridden explicitly | A permission; override precedence is `CORE-CONFIG-01`. |
104| §4.1, line 412 | MAY | Action references MAY be strings, functions, objects or symbols | A permission; deterministic resolution is `CORE-ROUTE-01` and `CORE-CONV-03`. |
105| §4.2, line 433 | MAY | An implementation MAY combine internal phases | A permission; the preserved guarantees are `CORE-LIFE-01`. |
106| §5.3, line 542 | MAY | One notification channel MAY be database storage | Clarifies `COMP-NOTIFY-01`. |
107| §5.7, line 578 | MAY | Shape evidence MAY use the listed forms | Lists acceptable evidence for `STD-TYPE-01`. |
108| §5.8, line 591 | MAY | An implementation MAY report extension badges | Badges are governed by the catalog's `extensions` block. |
109| §15, line 1334 | SHOULD | The conformance suite SHOULD encode at least the following requirements | An obligation on the protocol project, not on implementations. Met by the catalog. |
110| §15, line 1366 | SHOULD | The protocol repository SHOULD publish fixtures, expected outputs and a runner-neutral description | An obligation on the protocol project. Met by stacksjs/protocol. |
111
112That is 16 keyword uses on 14 lines: lines 265 and 271 each permit one thing
113and recommend another in the same sentence.
114
115## Traceability both ways
116
117Each catalog requirement gains an optional `sourceLines` array, and each
118`informative` entry carries its line. White-paper's `normative:check` then
119fails unless every keyword use in Part I is accounted for by exactly one
120requirement or informative entry, replacing the bare count it checks today.
121
122# Profiles and compatibility
123
124Behavioral, under RFC 0001: it adds SHOULD requirements and defines their
125result semantics. It adds no MUST that a conforming implementation can fail,
126since `CORE-REPORT-01` restates the report schema. No existing profile claim
127changes.
128
129# Conformance evidence
130
131- Fixtures for `CORE-ROUTE-03`, `STD-API-02` and `STD-QUEUE-02`, which are
132 behavioral. The others are inspection, reported from the implementation's
133 evidence.
134- Stacks evidence: resource routes and parameter constraints in its router;
135 models driving migrations, validation and the OpenAPI document; `buddy
136 generate:openapi`; typed config; delayed and scheduled jobs.
137- The catalog schema gains `informative` and `sourceLines`, and `check`
138 validates that informative lines and requirement source lines do not overlap.
139
140# Migration and rollback
141
142Existing reports stay valid: SHOULD results are new entries, and the report
143schema is unchanged. An implementation adds the new SHOULD results the next
144time it runs the suite. Rolling back removes the seven entries and the
145`informative` array with no effect on any profile claim.
146
147# Security and privacy
148
149None of the new requirements touch a trust boundary. Classifying a SHOULD NOT
150as informative does not weaken security: the observable authorization
151boundary it describes is already the MUST `COMP-VIEW-01`.
152
153# Alternatives
154
155- **Every SHOULD becomes a requirement.** Lines 1334 and 1366 bind the protocol
156 project, not implementations, and lines 265 and 271 cannot be observed from
157 outside an implementation.
158- **SHOULD failures gate profiles.** That would make a SHOULD a MUST in all but
159 name.
160- **Leave SHOULD and MAY uncatalogued.** That fails #2050's first acceptance
161 criterion, and leaves the §16 prose contradicting the report schema.
162
163# Unresolved questions
164
165- Whether `STD-GEN-01` belongs at Core. A dynamic host may have no
166 schema-bearing Model at all, which argues for Standard.
167- Whether the 55 MUST and 12 MUST NOT uses should get the same line-level
168 traceability in this RFC or a follow-up. 67 keyword uses map onto 47
169 requirements, because a list's lead-in MUST covers its items; `sourceLines`
170 makes that explicit.
171
172# Decision record
173
174Not yet reviewed.