truecourse 0.6.0-next.12 → 0.6.0-next.13
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/cli.mjs +67 -13
- package/package.json +1 -1
- package/server.mjs +46 -8
package/cli.mjs
CHANGED
|
@@ -129397,7 +129397,7 @@ function readToolVersion() {
|
|
|
129397
129397
|
if (cachedVersion)
|
|
129398
129398
|
return cachedVersion;
|
|
129399
129399
|
if (true) {
|
|
129400
|
-
cachedVersion = "0.6.0
|
|
129400
|
+
cachedVersion = "0.6.0";
|
|
129401
129401
|
return cachedVersion;
|
|
129402
129402
|
}
|
|
129403
129403
|
try {
|
|
@@ -143905,14 +143905,20 @@ Use sensible defaults when the spec doesn't spell them out:
|
|
|
143905
143905
|
on-violation {
|
|
143906
143906
|
status 401
|
|
143907
143907
|
error-code unauthenticated
|
|
143908
|
-
body ErrorEnvelope:error.envelope.standard
|
|
143909
143908
|
}
|
|
143910
143909
|
}
|
|
143911
143910
|
|
|
143912
|
-
Default \`on-violation\` is
|
|
143913
|
-
body
|
|
143914
|
-
|
|
143915
|
-
|
|
143911
|
+
Default \`on-violation\` is status 401, error-code \`unauthenticated\`. Add a
|
|
143912
|
+
\`body ErrorEnvelope:error.envelope.standard\` line ONLY when the spec/corpus
|
|
143913
|
+
actually establishes a standard error envelope \u2014 a dedicated errors /
|
|
143914
|
+
error-response section, an error-code catalog, or another slice that describes
|
|
143915
|
+
the error body shape. When the spec is SILENT about the error response body
|
|
143916
|
+
(common for terse auth docs that only state the scheme), OMIT the \`body\` line:
|
|
143917
|
+
a \`body\` reference to an envelope nothing defines is a dangling cross-reference
|
|
143918
|
+
that fails the validation gate, while an omitted body is faithful. See
|
|
143919
|
+
"Error-envelope references must be grounded" below. Default selector is
|
|
143920
|
+
\`path-glob "/api/**"\` when the spec says "all /api/* endpoints" without naming a
|
|
143921
|
+
more specific pattern.
|
|
143916
143922
|
|
|
143917
143923
|
When a spec describes role-based auth ("admin only", "moderators can \u2026"), produce
|
|
143918
143924
|
a SEPARATE \`auth-requirement\` with \`required-role <role>\`, identity
|
|
@@ -143947,7 +143953,8 @@ is the correct fallback when the slice lacks operation context.
|
|
|
143947
143953
|
on-violation {
|
|
143948
143954
|
status 403
|
|
143949
143955
|
error-code forbidden
|
|
143950
|
-
body ErrorEnvelope:error.envelope.standard
|
|
143956
|
+
// body ErrorEnvelope:error.envelope.standard only when that envelope is
|
|
143957
|
+
// defined in the corpus \u2014 see "Error-envelope references must be grounded".
|
|
143951
143958
|
}
|
|
143952
143959
|
}
|
|
143953
143960
|
|
|
@@ -144494,6 +144501,37 @@ response as a literal:
|
|
|
144494
144501
|
- Only declare a literal \`response 401/403 on \u2026\` when the spec describes the
|
|
144495
144502
|
response as standalone, NOT delegated to a rule.
|
|
144496
144503
|
|
|
144504
|
+
# Error-envelope references must be grounded
|
|
144505
|
+
|
|
144506
|
+
\`ErrorEnvelope:error.envelope.standard\` is a CROSS-REFERENCE, not a literal \u2014 it
|
|
144507
|
+
only resolves if a matching \`error-envelope error.envelope.standard { \u2026 }\`
|
|
144508
|
+
artifact exists somewhere in the corpus. Emitting the reference with nothing
|
|
144509
|
+
defining it produces a dangling cross-reference that fails the validation gate,
|
|
144510
|
+
exactly like referencing an undefined \`Enum:\`. This is the same prime-directive
|
|
144511
|
+
rule as enums ("never reference an enum without defining it"), applied to error
|
|
144512
|
+
bodies.
|
|
144513
|
+
|
|
144514
|
+
The rule applies EVERYWHERE an envelope can appear:
|
|
144515
|
+
\`on-violation { \u2026 body ErrorEnvelope:\u2026 }\` on auth-requirements and
|
|
144516
|
+
authorization-rules, and \`response \u2026 { body envelope ErrorEnvelope:\u2026 { \u2026 } }\`
|
|
144517
|
+
on operations.
|
|
144518
|
+
|
|
144519
|
+
- Reference \`ErrorEnvelope:error.envelope.standard\` ONLY when the spec actually
|
|
144520
|
+
establishes a standard error envelope: a dedicated errors / error-response
|
|
144521
|
+
section, an error-code catalog, or prose that names "the standard error
|
|
144522
|
+
envelope". In a multi-doc corpus the defining section may live in ANOTHER
|
|
144523
|
+
slice \u2014 that's fine, just like an \`Enum:\` defined in a sibling slice.
|
|
144524
|
+
- When you reference it AND the slice in front of you is the one that describes
|
|
144525
|
+
the envelope, ALSO emit the \`error-envelope error.envelope.standard { \u2026 }\`
|
|
144526
|
+
artifact \u2014 mirroring the described shape; never invent fields the spec does
|
|
144527
|
+
not list.
|
|
144528
|
+
- When the spec is SILENT about the error response body \u2014 no error section, no
|
|
144529
|
+
envelope, no error codes \u2014 do NOT emit the reference at all. Omit the \`body\`
|
|
144530
|
+
line from \`on-violation\`; on an operation response use a plain \`body \u2026\` only
|
|
144531
|
+
if the spec gives a shape, otherwise omit it. Faithful under-specification
|
|
144532
|
+
beats a dangling reference: never conjure a standard envelope just to fill the
|
|
144533
|
+
slot.
|
|
144534
|
+
|
|
144497
144535
|
# Naming conventions for artifact identities
|
|
144498
144536
|
|
|
144499
144537
|
Use these canonical identity formats:
|
|
@@ -148874,7 +148912,7 @@ function rulesFor(a) {
|
|
|
148874
148912
|
}
|
|
148875
148913
|
if (a.kind === "auth-requirement") {
|
|
148876
148914
|
if (!/\bon-violation\s*\{/.test(src)) {
|
|
148877
|
-
out.push("missing `on-violation { status ... error-code ... body ErrorEnvelope
|
|
148915
|
+
out.push("missing `on-violation { status ... error-code ... }` (add `body ErrorEnvelope:error.envelope.standard` only when that envelope is defined in the corpus).");
|
|
148878
148916
|
}
|
|
148879
148917
|
if (/\brequired-role\b/.test(src)) {
|
|
148880
148918
|
const hasBroadGlob = /selector\s+path-glob\s+"\/api\/(\*\*|\*)"/.test(src);
|
|
@@ -150497,11 +150535,27 @@ async function runContractsGenerate(options = {}) {
|
|
|
150497
150535
|
if (f2.run?.error) console.log(` \u2192 ${f2.run.error}`);
|
|
150498
150536
|
}
|
|
150499
150537
|
}
|
|
150500
|
-
|
|
150501
|
-
|
|
150502
|
-
|
|
150503
|
-
|
|
150538
|
+
const hardIssues = result.validationIssues.filter((i) => i.severity === "hard");
|
|
150539
|
+
const softIssues = result.validationIssues.filter((i) => i.severity === "soft");
|
|
150540
|
+
if (softIssues.length > 0) {
|
|
150541
|
+
const counts = /* @__PURE__ */ new Map();
|
|
150542
|
+
for (const issue of softIssues) {
|
|
150543
|
+
const line = `${issue.artifactKey}: ${issue.message}`;
|
|
150544
|
+
counts.set(line, (counts.get(line) ?? 0) + 1);
|
|
150504
150545
|
}
|
|
150546
|
+
O2.warn(
|
|
150547
|
+
`${counts.size} unresolved cross-reference${counts.size === 1 ? "" : "s"} (non-blocking \u2014 the referenced artifact wasn't generated; \`truecourse verify\` will flag any real drift):`
|
|
150548
|
+
);
|
|
150549
|
+
for (const [line, n] of counts) console.log(` ${line}${n > 1 ? ` (\xD7${n})` : ""}`);
|
|
150550
|
+
}
|
|
150551
|
+
if (hardIssues.length > 0) {
|
|
150552
|
+
O2.error(
|
|
150553
|
+
`${hardIssues.length} artifact${hardIssues.length === 1 ? " was" : "s were"} dropped (invalid \`.tc\` \u2014 parse error or duplicate identity):`
|
|
150554
|
+
);
|
|
150555
|
+
for (const issue of hardIssues) console.log(` ${issue.artifactKey}: ${issue.message}`);
|
|
150556
|
+
}
|
|
150557
|
+
const produced = options.diff ? result.write.proposed.length : result.write.written.length;
|
|
150558
|
+
if (produced === 0 && result.validationIssues.length > 0) {
|
|
150505
150559
|
gt("No contracts were written. Edit the spec or re-run after fixing.");
|
|
150506
150560
|
process.exit(1);
|
|
150507
150561
|
}
|
|
@@ -154293,7 +154347,7 @@ async function runHooksRun() {
|
|
|
154293
154347
|
|
|
154294
154348
|
// tools/cli/src/index.ts
|
|
154295
154349
|
var program2 = new Command();
|
|
154296
|
-
program2.name("truecourse").version("0.6.0
|
|
154350
|
+
program2.name("truecourse").version("0.6.0").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
|
|
154297
154351
|
var dashboardCmd = program2.command("dashboard").description("Start the TrueCourse dashboard and open it in your browser").option("--reconfigure", "Re-prompt for console vs background service mode").option("--service", "Run as a background service (skips mode prompt)").option("--console", "Run in this terminal (skips mode prompt)").action(async (options) => {
|
|
154298
154352
|
if (options.service && options.console) {
|
|
154299
154353
|
console.error("error: --service and --console are mutually exclusive");
|
package/package.json
CHANGED
package/server.mjs
CHANGED
|
@@ -158105,7 +158105,7 @@ function readToolVersion() {
|
|
|
158105
158105
|
if (cachedVersion)
|
|
158106
158106
|
return cachedVersion;
|
|
158107
158107
|
if (true) {
|
|
158108
|
-
cachedVersion = "0.6.0
|
|
158108
|
+
cachedVersion = "0.6.0";
|
|
158109
158109
|
return cachedVersion;
|
|
158110
158110
|
}
|
|
158111
158111
|
try {
|
|
@@ -164240,14 +164240,20 @@ Use sensible defaults when the spec doesn't spell them out:
|
|
|
164240
164240
|
on-violation {
|
|
164241
164241
|
status 401
|
|
164242
164242
|
error-code unauthenticated
|
|
164243
|
-
body ErrorEnvelope:error.envelope.standard
|
|
164244
164243
|
}
|
|
164245
164244
|
}
|
|
164246
164245
|
|
|
164247
|
-
Default \`on-violation\` is
|
|
164248
|
-
body
|
|
164249
|
-
|
|
164250
|
-
|
|
164246
|
+
Default \`on-violation\` is status 401, error-code \`unauthenticated\`. Add a
|
|
164247
|
+
\`body ErrorEnvelope:error.envelope.standard\` line ONLY when the spec/corpus
|
|
164248
|
+
actually establishes a standard error envelope \u2014 a dedicated errors /
|
|
164249
|
+
error-response section, an error-code catalog, or another slice that describes
|
|
164250
|
+
the error body shape. When the spec is SILENT about the error response body
|
|
164251
|
+
(common for terse auth docs that only state the scheme), OMIT the \`body\` line:
|
|
164252
|
+
a \`body\` reference to an envelope nothing defines is a dangling cross-reference
|
|
164253
|
+
that fails the validation gate, while an omitted body is faithful. See
|
|
164254
|
+
"Error-envelope references must be grounded" below. Default selector is
|
|
164255
|
+
\`path-glob "/api/**"\` when the spec says "all /api/* endpoints" without naming a
|
|
164256
|
+
more specific pattern.
|
|
164251
164257
|
|
|
164252
164258
|
When a spec describes role-based auth ("admin only", "moderators can \u2026"), produce
|
|
164253
164259
|
a SEPARATE \`auth-requirement\` with \`required-role <role>\`, identity
|
|
@@ -164282,7 +164288,8 @@ is the correct fallback when the slice lacks operation context.
|
|
|
164282
164288
|
on-violation {
|
|
164283
164289
|
status 403
|
|
164284
164290
|
error-code forbidden
|
|
164285
|
-
body ErrorEnvelope:error.envelope.standard
|
|
164291
|
+
// body ErrorEnvelope:error.envelope.standard only when that envelope is
|
|
164292
|
+
// defined in the corpus \u2014 see "Error-envelope references must be grounded".
|
|
164286
164293
|
}
|
|
164287
164294
|
}
|
|
164288
164295
|
|
|
@@ -164829,6 +164836,37 @@ response as a literal:
|
|
|
164829
164836
|
- Only declare a literal \`response 401/403 on \u2026\` when the spec describes the
|
|
164830
164837
|
response as standalone, NOT delegated to a rule.
|
|
164831
164838
|
|
|
164839
|
+
# Error-envelope references must be grounded
|
|
164840
|
+
|
|
164841
|
+
\`ErrorEnvelope:error.envelope.standard\` is a CROSS-REFERENCE, not a literal \u2014 it
|
|
164842
|
+
only resolves if a matching \`error-envelope error.envelope.standard { \u2026 }\`
|
|
164843
|
+
artifact exists somewhere in the corpus. Emitting the reference with nothing
|
|
164844
|
+
defining it produces a dangling cross-reference that fails the validation gate,
|
|
164845
|
+
exactly like referencing an undefined \`Enum:\`. This is the same prime-directive
|
|
164846
|
+
rule as enums ("never reference an enum without defining it"), applied to error
|
|
164847
|
+
bodies.
|
|
164848
|
+
|
|
164849
|
+
The rule applies EVERYWHERE an envelope can appear:
|
|
164850
|
+
\`on-violation { \u2026 body ErrorEnvelope:\u2026 }\` on auth-requirements and
|
|
164851
|
+
authorization-rules, and \`response \u2026 { body envelope ErrorEnvelope:\u2026 { \u2026 } }\`
|
|
164852
|
+
on operations.
|
|
164853
|
+
|
|
164854
|
+
- Reference \`ErrorEnvelope:error.envelope.standard\` ONLY when the spec actually
|
|
164855
|
+
establishes a standard error envelope: a dedicated errors / error-response
|
|
164856
|
+
section, an error-code catalog, or prose that names "the standard error
|
|
164857
|
+
envelope". In a multi-doc corpus the defining section may live in ANOTHER
|
|
164858
|
+
slice \u2014 that's fine, just like an \`Enum:\` defined in a sibling slice.
|
|
164859
|
+
- When you reference it AND the slice in front of you is the one that describes
|
|
164860
|
+
the envelope, ALSO emit the \`error-envelope error.envelope.standard { \u2026 }\`
|
|
164861
|
+
artifact \u2014 mirroring the described shape; never invent fields the spec does
|
|
164862
|
+
not list.
|
|
164863
|
+
- When the spec is SILENT about the error response body \u2014 no error section, no
|
|
164864
|
+
envelope, no error codes \u2014 do NOT emit the reference at all. Omit the \`body\`
|
|
164865
|
+
line from \`on-violation\`; on an operation response use a plain \`body \u2026\` only
|
|
164866
|
+
if the spec gives a shape, otherwise omit it. Faithful under-specification
|
|
164867
|
+
beats a dangling reference: never conjure a standard envelope just to fill the
|
|
164868
|
+
slot.
|
|
164869
|
+
|
|
164832
164870
|
# Naming conventions for artifact identities
|
|
164833
164871
|
|
|
164834
164872
|
Use these canonical identity formats:
|
|
@@ -165581,7 +165619,7 @@ function rulesFor(a) {
|
|
|
165581
165619
|
}
|
|
165582
165620
|
if (a.kind === "auth-requirement") {
|
|
165583
165621
|
if (!/\bon-violation\s*\{/.test(src)) {
|
|
165584
|
-
out.push("missing `on-violation { status ... error-code ... body ErrorEnvelope
|
|
165622
|
+
out.push("missing `on-violation { status ... error-code ... }` (add `body ErrorEnvelope:error.envelope.standard` only when that envelope is defined in the corpus).");
|
|
165585
165623
|
}
|
|
165586
165624
|
if (/\brequired-role\b/.test(src)) {
|
|
165587
165625
|
const hasBroadGlob = /selector\s+path-glob\s+"\/api\/(\*\*|\*)"/.test(src);
|