|
2 | 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", |
3 | 3 | "$id": "https://github.com/SocketDev/socket-repo-template-schema.json", |
4 | 4 | "title": "socket-repo-template per-repo config", |
5 | | - "type": "object", |
6 | 5 | "description": "Per-repo socket-repo-template config. Lives at the fleet repo root as `.socket-repo-template.json`.", |
| 6 | + "type": "object", |
7 | 7 | "required": ["schemaVersion", "repoName", "kind"], |
8 | | - "additionalProperties": false, |
9 | 8 | "properties": { |
10 | 9 | "$schema": { |
11 | | - "type": "string", |
12 | | - "description": "JSON Schema reference for editor autocompletion. Conventionally `./socket-repo-template-schema.json`." |
| 10 | + "description": "JSON Schema reference for editor autocompletion. Conventionally `./socket-repo-template-schema.json`.", |
| 11 | + "type": "string" |
13 | 12 | }, |
14 | 13 | "schemaVersion": { |
| 14 | + "description": "Schema version. Bump on breaking changes; readers gate on it.", |
15 | 15 | "const": 1, |
16 | | - "description": "Schema version. Bump on breaking changes; readers gate on it." |
| 16 | + "type": "number" |
17 | 17 | }, |
18 | 18 | "repoName": { |
19 | | - "type": "string", |
20 | 19 | "pattern": "^[a-z0-9][a-z0-9-]*$", |
21 | | - "description": "Canonical repo basename (e.g. `socket-lib`, `ultrathink`). Used for kind-independent exemptions like the oxlint `socket-lib` carve-out." |
| 20 | + "description": "Canonical repo basename (e.g. `socket-lib`, `ultrathink`). Used for kind-independent exemptions like the oxlint `socket-lib` carve-out.", |
| 21 | + "type": "string" |
22 | 22 | }, |
23 | 23 | "kind": { |
24 | 24 | "description": "Fleet repo category. Determines which opt-in files the repo must ship and which it must not. See README.md \"Fleet kinds\" for the table.", |
25 | | - "enum": [ |
26 | | - "single-package", |
27 | | - "mono-no-native", |
28 | | - "consumer", |
29 | | - "producer", |
30 | | - "both", |
31 | | - "lang-ports" |
| 25 | + "anyOf": [ |
| 26 | + { |
| 27 | + "const": "single-package", |
| 28 | + "type": "string" |
| 29 | + }, |
| 30 | + { |
| 31 | + "const": "mono-no-native", |
| 32 | + "type": "string" |
| 33 | + }, |
| 34 | + { |
| 35 | + "const": "consumer", |
| 36 | + "type": "string" |
| 37 | + }, |
| 38 | + { |
| 39 | + "const": "producer", |
| 40 | + "type": "string" |
| 41 | + }, |
| 42 | + { |
| 43 | + "const": "both", |
| 44 | + "type": "string" |
| 45 | + }, |
| 46 | + { |
| 47 | + "const": "lang-ports", |
| 48 | + "type": "string" |
| 49 | + } |
32 | 50 | ] |
33 | 51 | }, |
34 | 52 | "hooks": { |
35 | | - "type": "object", |
36 | 53 | "description": "Git-hook opt-ins.", |
37 | | - "additionalProperties": false, |
| 54 | + "type": "object", |
38 | 55 | "properties": { |
39 | 56 | "enablePrePush": { |
40 | | - "type": "boolean", |
41 | | - "description": "Wire `.husky/pre-push` → `.git-hooks/pre-push.mts`. Mandatory security gate; default true." |
| 57 | + "description": "Wire `.husky/pre-push` → `.git-hooks/pre-push.mts`. Mandatory security gate; default true.", |
| 58 | + "type": "boolean" |
42 | 59 | }, |
43 | 60 | "enableCommitMsg": { |
44 | | - "type": "boolean", |
45 | | - "description": "Wire `.husky/commit-msg` → `.git-hooks/commit-msg.mts`. Strips AI attribution; default true." |
| 61 | + "description": "Wire `.husky/commit-msg` → `.git-hooks/commit-msg.mts`. Strips AI attribution; default true.", |
| 62 | + "type": "boolean" |
46 | 63 | }, |
47 | 64 | "enablePreCommit": { |
48 | | - "type": "boolean", |
49 | | - "description": "Wire `.husky/pre-commit` → `.git-hooks/pre-commit.mts`. Lint + secret scan on staged files; default true." |
| 65 | + "description": "Wire `.husky/pre-commit` → `.git-hooks/pre-commit.mts`. Lint + secret scan on staged files; default true.", |
| 66 | + "type": "boolean" |
50 | 67 | }, |
51 | 68 | "preCommitVariant": { |
52 | | - "enum": ["lint-only", "lint-test"], |
53 | | - "description": "`lint-only` runs format + secret scan; `lint-test` adds vitest on touched packages. Default `lint-test`." |
| 69 | + "description": "`lint-only` runs format + secret scan; `lint-test` adds vitest on touched packages. Default `lint-test`.", |
| 70 | + "anyOf": [ |
| 71 | + { |
| 72 | + "const": "lint-only", |
| 73 | + "type": "string" |
| 74 | + }, |
| 75 | + { |
| 76 | + "const": "lint-test", |
| 77 | + "type": "string" |
| 78 | + } |
| 79 | + ] |
54 | 80 | } |
55 | 81 | } |
56 | 82 | }, |
57 | 83 | "scripts": { |
58 | | - "type": "object", |
59 | 84 | "description": "package.json script tracking overrides.", |
60 | | - "additionalProperties": false, |
| 85 | + "type": "object", |
61 | 86 | "properties": { |
62 | 87 | "required": { |
| 88 | + "description": "Override REQUIRED_SCRIPTS from manifest.mts. Usually omitted — the fleet default applies.", |
63 | 89 | "type": "array", |
64 | | - "items": { "type": "string" }, |
65 | | - "description": "Override REQUIRED_SCRIPTS from manifest.mts. Usually omitted — the fleet default applies." |
| 90 | + "items": { |
| 91 | + "type": "string" |
| 92 | + } |
66 | 93 | }, |
67 | 94 | "optional": { |
| 95 | + "description": "Per-script opt-in map keyed by script name. `true` = repo ships this RECOMMENDED script; `false` = explicit opt-out.", |
68 | 96 | "type": "object", |
69 | | - "additionalProperties": { "type": "boolean" }, |
70 | | - "description": "Per-script opt-in map keyed by script name. `true` = repo ships this RECOMMENDED script; `false` = explicit opt-out." |
| 97 | + "patternProperties": { |
| 98 | + "^(.*)$": { |
| 99 | + "type": "boolean" |
| 100 | + } |
| 101 | + } |
71 | 102 | }, |
72 | 103 | "bodyExempt": { |
| 104 | + "description": "Script names whose body is allowed to drift from the canonical form (e.g. socket-lib runs a richer test runner than the standard `node scripts/test.mts`). Each entry is the script name only.", |
73 | 105 | "type": "array", |
74 | | - "items": { "type": "string" }, |
75 | | - "description": "Script names whose body is allowed to drift from the canonical form (e.g. socket-lib runs a richer test runner than the standard `node scripts/test.mts`). Each entry is the script name only." |
| 106 | + "items": { |
| 107 | + "type": "string" |
| 108 | + } |
76 | 109 | } |
77 | 110 | } |
78 | 111 | }, |
79 | 112 | "lint": { |
80 | | - "type": "object", |
81 | 113 | "description": "oxlint profile.", |
82 | | - "additionalProperties": false, |
| 114 | + "type": "object", |
83 | 115 | "properties": { |
84 | 116 | "profile": { |
85 | | - "enum": ["standard", "rich"], |
86 | | - "description": "`standard` requires the fleet plugin set (import + typescript + unicorn). `rich` opts into a wider set; check the runner for the exact basenames currently exempted." |
| 117 | + "description": "`standard` requires the fleet plugin set (import + typescript + unicorn). `rich` opts into a wider set; check the runner for the exact basenames currently exempted.", |
| 118 | + "anyOf": [ |
| 119 | + { |
| 120 | + "const": "standard", |
| 121 | + "type": "string" |
| 122 | + }, |
| 123 | + { |
| 124 | + "const": "rich", |
| 125 | + "type": "string" |
| 126 | + } |
| 127 | + ] |
87 | 128 | } |
88 | 129 | } |
89 | 130 | }, |
90 | 131 | "workflows": { |
91 | | - "type": "object", |
92 | 132 | "description": "CI workflow opt-ins.", |
93 | | - "additionalProperties": false, |
| 133 | + "type": "object", |
94 | 134 | "properties": { |
95 | 135 | "ci": { |
96 | | - "type": "boolean", |
97 | | - "description": "Ship `.github/workflows/ci.yml`." |
| 136 | + "description": "Ship `.github/workflows/ci.yml`.", |
| 137 | + "type": "boolean" |
98 | 138 | }, |
99 | 139 | "weeklyUpdate": { |
100 | | - "type": "boolean", |
101 | | - "description": "Ship `.github/workflows/weekly-update.yml`." |
| 140 | + "description": "Ship `.github/workflows/weekly-update.yml`.", |
| 141 | + "type": "boolean" |
102 | 142 | }, |
103 | 143 | "provenance": { |
104 | | - "type": "boolean", |
105 | | - "description": "Repo publishes with npm provenance (OIDC). Hint for setup helpers; not enforced by the checker today." |
| 144 | + "description": "Repo publishes with npm provenance (OIDC). Hint for setup helpers; not enforced by the checker today.", |
| 145 | + "type": "boolean" |
106 | 146 | }, |
107 | 147 | "requirePinnedFullSha": { |
108 | | - "type": "boolean", |
109 | | - "description": "Enforce 40-char SHA pins on every `uses:` ref. Defaults to true; an opt-out is reserved for special cases (e.g. workflow-dispatch test rigs) and currently has no consumer." |
| 148 | + "description": "Enforce 40-char SHA pins on every `uses:` ref. Defaults to true; an opt-out is reserved for special cases (e.g. workflow-dispatch test rigs) and currently has no consumer.", |
| 149 | + "type": "boolean" |
110 | 150 | } |
111 | 151 | } |
112 | 152 | }, |
113 | 153 | "claude": { |
114 | | - "type": "object", |
115 | 154 | "description": "Claude Code opt-ins.", |
116 | | - "additionalProperties": false, |
| 155 | + "type": "object", |
117 | 156 | "properties": { |
118 | 157 | "includeSecurityScanSkill": { |
119 | | - "type": "boolean", |
120 | | - "description": "Ship `.claude/skills/security-scan/SKILL.md`." |
| 158 | + "description": "Ship `.claude/skills/security-scan/SKILL.md`.", |
| 159 | + "type": "boolean" |
121 | 160 | }, |
122 | 161 | "includeSharedSkills": { |
123 | | - "type": "boolean", |
124 | | - "description": "Ship `.claude/skills/_shared/*` — env-check, path-guard-rule, report-format, security-tools, verify-build." |
| 162 | + "description": "Ship `.claude/skills/_shared/*` — env-check, path-guard-rule, report-format, security-tools, verify-build.", |
| 163 | + "type": "boolean" |
125 | 164 | }, |
126 | 165 | "includeUpdatingSkill": { |
127 | | - "type": "boolean", |
128 | | - "description": "Ship the dependency-update skill. Reserved — no consumer wired today." |
| 166 | + "description": "Ship the dependency-update skill. Reserved — no consumer wired today.", |
| 167 | + "type": "boolean" |
129 | 168 | } |
130 | 169 | } |
131 | 170 | }, |
132 | 171 | "workspace": { |
133 | | - "type": "object", |
134 | 172 | "description": "pnpm-workspace.yaml setting hints. The runner reads from the YAML; this block exists for repos that prefer to declare intent in JSON.", |
135 | | - "additionalProperties": false, |
| 173 | + "type": "object", |
136 | 174 | "properties": { |
137 | 175 | "allowBuilds": { |
| 176 | + "description": "pnpm `onlyBuiltDependencies` allowlist. Map a package name to true/false to grant/deny build scripts.", |
138 | 177 | "type": "object", |
139 | | - "additionalProperties": { "type": "boolean" }, |
140 | | - "description": "pnpm `onlyBuiltDependencies` allowlist. Map a package name to true/false to grant/deny build scripts." |
| 178 | + "patternProperties": { |
| 179 | + "^(.*)$": { |
| 180 | + "type": "boolean" |
| 181 | + } |
| 182 | + } |
141 | 183 | }, |
142 | 184 | "blockExoticSubdeps": { |
143 | | - "type": "boolean", |
144 | | - "description": "Refuse transitive git/tarball subdeps (direct git deps still allowed). Required true; the field exists so a repo can document the intent locally." |
| 185 | + "description": "Refuse transitive git/tarball subdeps (direct git deps still allowed). Required true; the field exists so a repo can document the intent locally.", |
| 186 | + "type": "boolean" |
145 | 187 | }, |
146 | 188 | "minimumReleaseAge": { |
147 | | - "type": "integer", |
148 | 189 | "minimum": 0, |
149 | | - "description": "Soak window in minutes before installing freshly-published packages. Fleet default 10080 (= 7 days)." |
| 190 | + "description": "Soak window in minutes before installing freshly-published packages. Fleet default 10080 (= 7 days).", |
| 191 | + "type": "integer" |
150 | 192 | }, |
151 | 193 | "minimumReleaseAgeExclude": { |
| 194 | + "description": "Scopes / package patterns exempt from the soak window. Socket-owned scopes typically listed here.", |
152 | 195 | "type": "array", |
153 | | - "items": { "type": "string" }, |
154 | | - "description": "Scopes / package patterns exempt from the soak window. Socket-owned scopes typically listed here." |
| 196 | + "items": { |
| 197 | + "type": "string" |
| 198 | + } |
155 | 199 | }, |
156 | 200 | "resolutionMode": { |
157 | | - "enum": ["highest", "lowest-direct"], |
158 | | - "description": "pnpm `resolutionMode`. Fleet default `highest`." |
| 201 | + "description": "pnpm `resolutionMode`. Fleet default `highest`.", |
| 202 | + "anyOf": [ |
| 203 | + { |
| 204 | + "const": "highest", |
| 205 | + "type": "string" |
| 206 | + }, |
| 207 | + { |
| 208 | + "const": "lowest-direct", |
| 209 | + "type": "string" |
| 210 | + } |
| 211 | + ] |
159 | 212 | }, |
160 | 213 | "trustPolicy": { |
161 | | - "enum": ["no-downgrade", "match-spec"], |
162 | | - "description": "pnpm `trustPolicy`. Fleet default `no-downgrade`." |
| 214 | + "description": "pnpm `trustPolicy`. Fleet default `no-downgrade`.", |
| 215 | + "anyOf": [ |
| 216 | + { |
| 217 | + "const": "no-downgrade", |
| 218 | + "type": "string" |
| 219 | + }, |
| 220 | + { |
| 221 | + "const": "match-spec", |
| 222 | + "type": "string" |
| 223 | + } |
| 224 | + ] |
163 | 225 | } |
164 | 226 | } |
165 | 227 | } |
|
0 commit comments