Skip to content

Commit 83596a9

Browse files
Testclaude
authored andcommitted
fix(scripts): render permission-set fields in SCHEMAS.md, add parse context
Two Copilot review fixes on the permission-sets PR: - generate-schemas.js: permission-set defs (title/detail/permissions) now render in SCHEMAS.md instead of producing empty header-only sections. - generate-exports.js: extract a readLexicon() helper that rethrows JSON.parse failures with the offending file path, mirroring generate-schemas.js, so codegen errors are traceable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6e02162 commit 83596a9

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

.changeset/permission-sets-crud.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ There are **three** sets rather than one because the spec requires it: a permiss
1111
Permission sets are published as-is (they are the source of truth for what gets published to AT Protocol) but have no TypeScript shape — `lex gen-api` cannot generate code for `permission-set` defs. They are therefore excluded from the codegen globs (`gen-api`/`gen-md`/`gen-ts`) and from `generated/exports.ts`, while still shipping as raw lexicon JSON.
1212

1313
Collection lists are enumerated explicitly because the spec forbids wildcards inside a permission set; they must be kept in sync as record types are added. See `docs/design/permission-sets.md`.
14+
15+
The generated `SCHEMAS.md` reference now renders permission-set entries (title, detail, and the resource/collections/actions each set grants) instead of leaving them as empty sections.

SCHEMAS.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ Hypercerts-specific lexicons for tracking impact work and claims.
99

1010
### `org.hypercerts.authWrite`
1111

12+
**Title:** Manage your Hypercerts data
13+
14+
**Detail:** Create, edit, and delete your Hypercerts records (impact claims, evaluations, funding, and related data).
15+
16+
**Resource:** `repo`
17+
18+
**Collections:** `org.hypercerts.claim.activity`, `org.hypercerts.claim.contribution`, `org.hypercerts.claim.contributorInformation`, `org.hypercerts.claim.rights`, `org.hypercerts.collection`, `org.hypercerts.context.acknowledgement`, `org.hypercerts.context.attachment`, `org.hypercerts.context.evaluation`, `org.hypercerts.context.measurement`, `org.hypercerts.funding.receipt`, `org.hypercerts.workscope.tag`
19+
20+
**Actions:** `create`, `update`, `delete`
21+
1222
---
1323

1424
### `org.hypercerts.claim.activity`
@@ -490,6 +500,16 @@ A labeled URL reference.
490500

491501
### `app.certified.authWrite`
492502

503+
**Title:** Manage your Certified data
504+
505+
**Detail:** Create, edit, and delete your Certified records (profile, badges, follows, wallet links, and related data).
506+
507+
**Resource:** `repo`
508+
509+
**Collections:** `app.certified.actor.organization`, `app.certified.actor.profile`, `app.certified.badge.award`, `app.certified.badge.definition`, `app.certified.badge.response`, `app.certified.graph.follow`, `app.certified.link.evm`, `app.certified.location`, `app.certified.signature.proof`
510+
511+
**Actions:** `create`, `update`, `delete`
512+
493513
---
494514

495515
### `app.certified.graph.follow`
@@ -732,6 +752,16 @@ Specifies the sub-string range a facet feature applies to. Start index is inclus
732752

733753
### `org.hyperboards.authWrite`
734754

755+
**Title:** Manage your Hyperboards data
756+
757+
**Detail:** Create, edit, and delete your Hyperboards records (board configurations and display profiles).
758+
759+
**Resource:** `repo`
760+
761+
**Collections:** `org.hyperboards.board`, `org.hyperboards.displayProfile`
762+
763+
**Actions:** `create`, `update`, `delete`
764+
735765
---
736766

737767
### `org.hyperboards.board`

scripts/generate-exports.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
2222
const projectRoot = join(__dirname, "..");
2323
const lexiconsDir = join(projectRoot, "lexicons");
2424

25+
/**
26+
* Read and parse a lexicon JSON file, rethrowing parse failures with the
27+
* offending file path so codegen errors are traceable (mirrors
28+
* scripts/generate-schemas.js).
29+
*/
30+
function readLexicon(filePath) {
31+
const content = readFileSync(join(lexiconsDir, filePath), "utf-8");
32+
33+
try {
34+
return JSON.parse(content);
35+
} catch (error) {
36+
const message = error instanceof Error ? error.message : String(error);
37+
throw new Error(`Failed to parse lexicon ${filePath}: ${message}`);
38+
}
39+
}
40+
2541
/**
2642
* Recursively find all JSON files in a directory
2743
*/
@@ -163,7 +179,7 @@ function generateIndex() {
163179
.sort()
164180
.map((filePath) => ({
165181
filePath,
166-
doc: JSON.parse(readFileSync(join(lexiconsDir, filePath), "utf-8")),
182+
doc: readLexicon(filePath),
167183
}))
168184
// Permission-set lexicons have no TS shape — lex gen-api cannot codegen them
169185
// — so they are excluded from `generated/` here, by the SAME content check

scripts/generate-schemas.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,38 @@ function generateDescription(description) {
272272
return description ? [`**Description:** ${description}`, ""] : [];
273273
}
274274

275+
function generatePermissionSetSection(mainDef) {
276+
const output = [];
277+
278+
if (mainDef.title) output.push(`**Title:** ${mainDef.title}`, "");
279+
if (mainDef.detail) output.push(`**Detail:** ${mainDef.detail}`, "");
280+
281+
const permissions = mainDef.permissions || [];
282+
for (const permission of permissions) {
283+
const collections = (permission.collection || [])
284+
.map((c) => `\`${c}\``)
285+
.join(", ");
286+
const actions = (permission.action || []).map((a) => `\`${a}\``).join(", ");
287+
output.push(`**Resource:** \`${permission.resource}\``, "");
288+
if (collections) output.push(`**Collections:** ${collections}`, "");
289+
if (actions) output.push(`**Actions:** ${actions}`, "");
290+
}
291+
292+
return output;
293+
}
294+
275295
function generateMainSection(mainDef, lexicon) {
276296
const output = [];
277297

278298
if (!mainDef) return output;
279299

300+
// Permission sets have no properties — render their title/detail/permissions
301+
// so the section isn't blank in the reference.
302+
if (mainDef.type === "permission-set") {
303+
const permOutput = generatePermissionSetSection(mainDef);
304+
return { output: permOutput, hasProperties: false, hasPropertyRows: false };
305+
}
306+
280307
output.push(...generateDescription(mainDef.description));
281308

282309
// Object types (e.g., celExpression) have no record key

0 commit comments

Comments
 (0)