@wairon/sdk 6.7.4-dev.1 → 6.7.4-dev.10
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/README.md +24 -1
- package/dist/index.d.ts +30 -2
- package/dist/index.js +155 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,8 +18,11 @@ stays in wairon core and runs after extraction.
|
|
|
18
18
|
import {
|
|
19
19
|
scaffoldPack, // scaffold a new pack project (declarative | code)
|
|
20
20
|
buildPack, // build an installable .wpack from a pack directory
|
|
21
|
-
inspectArchive, // inspect + version-check a .wpack without extracting
|
|
21
|
+
inspectArchive, // inspect + version-check a .wpack without extracting (entries vetted under limits first)
|
|
22
|
+
readPack, // read a .wpack in memory under the guards: envelope, inner manifest, files
|
|
22
23
|
extractPack, // SAFELY extract a .wpack under enforced limits
|
|
24
|
+
PackArchiveError, // what every .wpack reader throws; match on its `code`
|
|
25
|
+
packContentDigest, // the content integrity (sha256-<hex>) wairon pins, over a pack's files
|
|
23
26
|
} from '@wairon/sdk';
|
|
24
27
|
```
|
|
25
28
|
|
|
@@ -32,6 +35,26 @@ non-regular entries, and anything over the caps (entry count, total inflated
|
|
|
32
35
|
size, per-entry size, compression ratio, path depth). Integrity is verified
|
|
33
36
|
before the tree is written, so a tampered pack never lands.
|
|
34
37
|
|
|
38
|
+
`inspectArchive` and `readPack` run the same guards: every entry is vetted under the
|
|
39
|
+
limits (default or yours) before anything, the envelope included, is inflated. `readPack`
|
|
40
|
+
returns `{ manifest, packManifest, files }` and writes nothing: the parsed envelope, the inner
|
|
41
|
+
pack manifest as authored (`pack.yaml`, or `package.json` of a code pack) and every approved
|
|
42
|
+
file, integrity-checked when the envelope carries digests and checked for envelope/inner
|
|
43
|
+
name and version agreement. `extractPack` is `readPack` followed by the write.
|
|
44
|
+
|
|
45
|
+
Every refusal is a `PackArchiveError` with a stable `code` (match on it, not on the message):
|
|
46
|
+
|
|
47
|
+
| code | meaning |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `NOT_A_PACK` | no `wairon-pack.yaml` envelope |
|
|
50
|
+
| `UNSAFE_PATH` | symlink, non-file kind, or an absolute / backslash / drive-letter / `..` / escaping path |
|
|
51
|
+
| `LIMIT_EXCEEDED` | an entry or the archive is over a cap (entry size, ratio, depth, count, total) |
|
|
52
|
+
| `ENVELOPE_INVALID` | the envelope is not a YAML mapping, or a required field is missing or mistyped |
|
|
53
|
+
| `FORMAT_VERSION_UNSUPPORTED` | the envelope format is newer than this SDK understands |
|
|
54
|
+
| `PACK_MANIFEST_INVALID` | the inner pack manifest is missing, unreadable or not a mapping |
|
|
55
|
+
| `IDENTITY_MISMATCH` | envelope name/version differ from the inner manifest's |
|
|
56
|
+
| `DIGEST_MISMATCH` | a file's bytes do not match the digest the envelope carries |
|
|
57
|
+
|
|
35
58
|
Whole in-memory buffers only (never streams) — the zip-bomb guard must enumerate
|
|
36
59
|
entry sizes *before* decompression. The `bytes` surface is `Uint8Array` (Node's
|
|
37
60
|
`Buffer` is accepted transparently).
|
package/dist/index.d.ts
CHANGED
|
@@ -80,6 +80,18 @@ interface PackExtractionLimits {
|
|
|
80
80
|
/** Max path nesting depth (default 16). */
|
|
81
81
|
maxDepth?: number;
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* A `.wpack` archive read in memory under the extraction guards, nothing
|
|
85
|
+
* written: its envelope, its parsed inner pack manifest and its files.
|
|
86
|
+
*/
|
|
87
|
+
interface PackContents {
|
|
88
|
+
/** The parsed envelope. */
|
|
89
|
+
manifest: PackArchiveManifest;
|
|
90
|
+
/** The inner pack manifest as authored (pack.yaml, or package.json of a code pack). */
|
|
91
|
+
packManifest: Record<string, unknown>;
|
|
92
|
+
/** Every approved file, inflated and integrity-checked when digests are carried. */
|
|
93
|
+
files: PackFile[];
|
|
94
|
+
}
|
|
83
95
|
/**
|
|
84
96
|
* Inputs to `wairon pack init`: the identity and variant of the pack project to
|
|
85
97
|
* scaffold, and where to write it.
|
|
@@ -283,12 +295,28 @@ interface SddRule {
|
|
|
283
295
|
*/
|
|
284
296
|
declare function defineRule(rule: SddRule): SddRule;
|
|
285
297
|
|
|
298
|
+
/** Why a .wpack archive was refused. */
|
|
299
|
+
type PackArchiveErrorCode = 'NOT_A_PACK' | 'UNSAFE_PATH' | 'LIMIT_EXCEEDED' | 'ENVELOPE_INVALID' | 'FORMAT_VERSION_UNSUPPORTED' | 'PACK_MANIFEST_INVALID' | 'IDENTITY_MISMATCH' | 'DIGEST_MISMATCH';
|
|
300
|
+
/** A .wpack archive was refused: a stable `code` beside a human message. */
|
|
301
|
+
declare class PackArchiveError extends Error {
|
|
302
|
+
readonly code: PackArchiveErrorCode;
|
|
303
|
+
constructor(code: PackArchiveErrorCode, message: string);
|
|
304
|
+
}
|
|
305
|
+
|
|
286
306
|
/** Scaffold a new pack project (declarative or code) into a directory; returns the created file paths. */
|
|
287
307
|
declare function scaffoldPack(request: PackScaffoldRequest): string[];
|
|
288
308
|
/** Build an installable .wpack archive from a pack directory. */
|
|
289
309
|
declare function buildPack(sourceDir: string): PackBuildResult;
|
|
310
|
+
/**
|
|
311
|
+
* A pack's content integrity (`sha256-<hex>`) over its files as extracted —
|
|
312
|
+
* the digest project.yaml pins and a registry publishes, one implementation
|
|
313
|
+
* for every consumer.
|
|
314
|
+
*/
|
|
315
|
+
declare function packContentDigest(files: readonly PackFile[]): string;
|
|
290
316
|
/** Inspect + verify a .wpack archive without extracting it. */
|
|
291
|
-
declare function inspectArchive(archive: Uint8Array): PackArchiveInfo;
|
|
317
|
+
declare function inspectArchive(archive: Uint8Array, limits?: PackExtractionLimits): PackArchiveInfo;
|
|
318
|
+
/** Read a .wpack archive in memory under the extraction guards; nothing is written. */
|
|
319
|
+
declare function readPack(archive: Uint8Array, limits?: PackExtractionLimits): PackContents;
|
|
292
320
|
/** Safely extract a .wpack archive into a destination directory under enforced limits. */
|
|
293
321
|
declare function extractPack(archive: Uint8Array, destDir: string, limits?: PackExtractionLimits): PackExtractionResult;
|
|
294
322
|
/** Pack a project's spec tree — the supplied roots' .wai directories — into a .waitree archive. */
|
|
@@ -298,4 +326,4 @@ declare function inspectTreeArchive(archive: Uint8Array): TreeArchiveInfo;
|
|
|
298
326
|
/** Safely extract a .waitree archive into a destination project root under enforced limits. */
|
|
299
327
|
declare function extractTreeArchive(archive: Uint8Array, destDir: string, limits?: PackExtractionLimits, refuseExecutableEntries?: boolean): TreeExtractionResult;
|
|
300
328
|
|
|
301
|
-
export { type ArchiveEntryMeta, type Finding, type PackArchiveInfo, type PackArchiveManifest, type PackBuildResult, type PackExtractionLimits, type PackExtractionPlan, type PackExtractionResult, type PackFile, type PackScaffoldRequest, type RuleContext, type RuleSeverity, type RuleSpecNode, type SddRule, type TreeArchiveInfo, type TreeArchiveManifest, type TreeBuildResult, type TreeExtractionResult, type TreeRootSource, buildPack, buildTreeArchive, defineRule, extractPack, extractTreeArchive, inspectArchive, inspectTreeArchive, scaffoldPack };
|
|
329
|
+
export { type ArchiveEntryMeta, type Finding, PackArchiveError, type PackArchiveErrorCode, type PackArchiveInfo, type PackArchiveManifest, type PackBuildResult, type PackContents, type PackExtractionLimits, type PackExtractionPlan, type PackExtractionResult, type PackFile, type PackScaffoldRequest, type RuleContext, type RuleSeverity, type RuleSpecNode, type SddRule, type TreeArchiveInfo, type TreeArchiveManifest, type TreeBuildResult, type TreeExtractionResult, type TreeRootSource, buildPack, buildTreeArchive, defineRule, extractPack, extractTreeArchive, inspectArchive, inspectTreeArchive, packContentDigest, readPack, scaffoldPack };
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ var require_package = __commonJS({
|
|
|
35
35
|
"package.json"(exports2, module2) {
|
|
36
36
|
module2.exports = {
|
|
37
37
|
name: "@wairon/sdk",
|
|
38
|
-
version: "6.7.4-dev.
|
|
38
|
+
version: "6.7.4-dev.10",
|
|
39
39
|
description: "Experimental: wairon pack-archive (.wpack) format authority and authoring toolkit \u2014 scaffold, build, inspect, and safely extract wairon extension packs.",
|
|
40
40
|
keywords: [
|
|
41
41
|
"wairon",
|
|
@@ -89,6 +89,7 @@ var require_package = __commonJS({
|
|
|
89
89
|
// src/index.ts
|
|
90
90
|
var src_exports = {};
|
|
91
91
|
__export(src_exports, {
|
|
92
|
+
PackArchiveError: () => PackArchiveError,
|
|
92
93
|
buildPack: () => buildPack2,
|
|
93
94
|
buildTreeArchive: () => buildTreeArchive2,
|
|
94
95
|
defineRule: () => defineRule,
|
|
@@ -96,6 +97,8 @@ __export(src_exports, {
|
|
|
96
97
|
extractTreeArchive: () => extractTreeArchive2,
|
|
97
98
|
inspectArchive: () => inspectArchive2,
|
|
98
99
|
inspectTreeArchive: () => inspectTreeArchive2,
|
|
100
|
+
packContentDigest: () => packContentDigest,
|
|
101
|
+
readPack: () => readPack2,
|
|
99
102
|
scaffoldPack: () => scaffoldPack2
|
|
100
103
|
});
|
|
101
104
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -107,6 +110,30 @@ var import_js_yaml3 = require("js-yaml");
|
|
|
107
110
|
// src/codec.ts
|
|
108
111
|
var import_js_yaml = require("js-yaml");
|
|
109
112
|
var import_crypto = require("crypto");
|
|
113
|
+
|
|
114
|
+
// src/errors.ts
|
|
115
|
+
var PackArchiveError = class _PackArchiveError extends Error {
|
|
116
|
+
constructor(code, message) {
|
|
117
|
+
super(message);
|
|
118
|
+
this.name = "PackArchiveError";
|
|
119
|
+
this.code = code;
|
|
120
|
+
Object.setPrototypeOf(this, _PackArchiveError.prototype);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// src/codec.ts
|
|
125
|
+
var DIGEST_EXCLUDED = /* @__PURE__ */ new Set([".install.yaml", ".git", "node_modules", ".DS_Store"]);
|
|
126
|
+
function contentDigest(files) {
|
|
127
|
+
const kept = files.map((file) => ({ path: file.path.replace(/\\/g, "/").replace(/^\/+/, ""), contents: file.contents })).filter((file) => !file.path.split("/").some((segment) => DIGEST_EXCLUDED.has(segment))).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
128
|
+
const hash = (0, import_crypto.createHash)("sha256");
|
|
129
|
+
for (const file of kept) {
|
|
130
|
+
hash.update(file.path);
|
|
131
|
+
hash.update("\0");
|
|
132
|
+
hash.update(file.contents);
|
|
133
|
+
hash.update("\0");
|
|
134
|
+
}
|
|
135
|
+
return `sha256-${hash.digest("hex")}`;
|
|
136
|
+
}
|
|
110
137
|
var ENVELOPE_FILENAME = "wairon-pack.yaml";
|
|
111
138
|
var SUPPORTED_FORMAT_VERSION = 1;
|
|
112
139
|
var DEFAULTS = {
|
|
@@ -117,10 +144,18 @@ var DEFAULTS = {
|
|
|
117
144
|
maxDepth: 16
|
|
118
145
|
};
|
|
119
146
|
function parseManifest(text) {
|
|
120
|
-
|
|
147
|
+
let raw;
|
|
148
|
+
try {
|
|
149
|
+
raw = (0, import_js_yaml.load)(text);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
throw new PackArchiveError("ENVELOPE_INVALID", `malformed pack envelope (not valid YAML): ${err.message}`);
|
|
152
|
+
}
|
|
121
153
|
const manifest = validateEnvelope(raw);
|
|
122
154
|
if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {
|
|
123
|
-
throw new
|
|
155
|
+
throw new PackArchiveError(
|
|
156
|
+
"FORMAT_VERSION_UNSUPPORTED",
|
|
157
|
+
`unsupported pack-archive formatVersion ${manifest.formatVersion} (newer than this wairon understands)`
|
|
158
|
+
);
|
|
124
159
|
}
|
|
125
160
|
return manifest;
|
|
126
161
|
}
|
|
@@ -154,27 +189,39 @@ function planExtraction(entries, limits) {
|
|
|
154
189
|
let total = 0;
|
|
155
190
|
for (const entry of entries) {
|
|
156
191
|
if (isSymlinkOrNonRegular(entry.kind) || isStructurallyUnsafePath(entry.path)) {
|
|
157
|
-
rejectUnsafe();
|
|
192
|
+
rejectUnsafe(entry.path);
|
|
158
193
|
}
|
|
159
194
|
if (entry.kind === "dir") continue;
|
|
160
195
|
const normalized = normalizeRelPath(entry.path);
|
|
161
|
-
if (escapesDestination(normalized)
|
|
162
|
-
rejectUnsafe();
|
|
196
|
+
if (escapesDestination(normalized)) {
|
|
197
|
+
rejectUnsafe(entry.path);
|
|
163
198
|
}
|
|
164
|
-
if (
|
|
165
|
-
|
|
199
|
+
if (pathDepth(normalized) > caps.maxDepth) {
|
|
200
|
+
rejectLimit(`entry "${entry.path}" is nested deeper than maxDepth (${caps.maxDepth})`);
|
|
201
|
+
}
|
|
202
|
+
if (entry.uncompressedSize > caps.maxEntryBytes) {
|
|
203
|
+
rejectLimit(`entry "${entry.path}" is larger than maxEntryBytes (${caps.maxEntryBytes})`);
|
|
204
|
+
}
|
|
205
|
+
if (compressionRatio(entry) > caps.maxCompressionRatio) {
|
|
206
|
+
rejectLimit(`entry "${entry.path}" exceeds maxCompressionRatio (${caps.maxCompressionRatio}:1)`);
|
|
166
207
|
}
|
|
167
208
|
approved.push(normalized);
|
|
168
209
|
total += entry.uncompressedSize;
|
|
169
210
|
}
|
|
170
|
-
if (approved.length > caps.maxEntries
|
|
171
|
-
|
|
211
|
+
if (approved.length > caps.maxEntries) {
|
|
212
|
+
rejectLimit(`archive holds more than maxEntries (${caps.maxEntries}) files`);
|
|
213
|
+
}
|
|
214
|
+
if (total > caps.maxTotalUncompressedBytes) {
|
|
215
|
+
rejectLimit(`archive inflates beyond maxTotalUncompressedBytes (${caps.maxTotalUncompressedBytes})`);
|
|
172
216
|
}
|
|
173
217
|
return { paths: approved, totalUncompressedBytes: total };
|
|
174
218
|
}
|
|
175
219
|
function verifyIdentity(manifest, packName, packVersion) {
|
|
176
220
|
if (manifest.name !== packName || manifest.version !== packVersion) {
|
|
177
|
-
throw new
|
|
221
|
+
throw new PackArchiveError(
|
|
222
|
+
"IDENTITY_MISMATCH",
|
|
223
|
+
`envelope identity mismatch: envelope says ${manifest.name}@${manifest.version}, inner pack manifest says ${packName}@${packVersion}`
|
|
224
|
+
);
|
|
178
225
|
}
|
|
179
226
|
}
|
|
180
227
|
function verifyIntegrity(manifest, files) {
|
|
@@ -182,10 +229,18 @@ function verifyIntegrity(manifest, files) {
|
|
|
182
229
|
return false;
|
|
183
230
|
}
|
|
184
231
|
const digests = manifest.entryDigests;
|
|
232
|
+
const held = new Set(files.map((file) => file.path));
|
|
233
|
+
const missing = Object.keys(digests).find((path3) => !held.has(path3));
|
|
234
|
+
if (missing !== void 0) {
|
|
235
|
+
throw new PackArchiveError("DIGEST_MISMATCH", `integrity digest lists "${missing}", which the archive does not hold`);
|
|
236
|
+
}
|
|
237
|
+
if (manifest.digest !== void 0 && manifest.digest !== sha256(canonicalDigestBytes(digests))) {
|
|
238
|
+
throw new PackArchiveError("DIGEST_MISMATCH", "integrity digest mismatch for the overall digest");
|
|
239
|
+
}
|
|
185
240
|
for (const file of files) {
|
|
186
241
|
if (file.path === ENVELOPE_FILENAME) continue;
|
|
187
242
|
if (sha256(file.contents) !== digests[file.path]) {
|
|
188
|
-
throw new
|
|
243
|
+
throw new PackArchiveError("DIGEST_MISMATCH", `integrity digest mismatch for "${file.path}"`);
|
|
189
244
|
}
|
|
190
245
|
}
|
|
191
246
|
return true;
|
|
@@ -197,7 +252,10 @@ function sealIntegrity(manifest, files, generatedBy, generatedAt) {
|
|
|
197
252
|
entryDigests[file.path] = sha256(file.contents);
|
|
198
253
|
}
|
|
199
254
|
const digest = sha256(canonicalDigestBytes(entryDigests));
|
|
200
|
-
|
|
255
|
+
const sealed = { ...manifest, entryDigests, digest, generatedBy };
|
|
256
|
+
if (generatedAt !== void 0) sealed.generatedAt = generatedAt;
|
|
257
|
+
else delete sealed.generatedAt;
|
|
258
|
+
return sealed;
|
|
201
259
|
}
|
|
202
260
|
function checkCompatibility(manifest, waironVersion) {
|
|
203
261
|
if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {
|
|
@@ -208,21 +266,57 @@ function checkCompatibility(manifest, waironVersion) {
|
|
|
208
266
|
}
|
|
209
267
|
return true;
|
|
210
268
|
}
|
|
211
|
-
function
|
|
212
|
-
|
|
269
|
+
function parseInnerManifest(manifest, files) {
|
|
270
|
+
const innerPath = manifest.kind === "code" ? "package.json" : manifest.entry;
|
|
271
|
+
const inner = files.find((file) => file.path === innerPath);
|
|
272
|
+
if (!inner) {
|
|
273
|
+
throw new PackArchiveError("PACK_MANIFEST_INVALID", `inner pack manifest "${innerPath}" is missing`);
|
|
274
|
+
}
|
|
275
|
+
const text = new TextDecoder().decode(inner.contents);
|
|
276
|
+
let parsed;
|
|
277
|
+
try {
|
|
278
|
+
parsed = manifest.kind === "code" ? JSON.parse(text) : (0, import_js_yaml.load)(text);
|
|
279
|
+
} catch {
|
|
280
|
+
parsed = void 0;
|
|
281
|
+
}
|
|
282
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
283
|
+
throw new PackArchiveError("PACK_MANIFEST_INVALID", `inner pack manifest "${innerPath}" is not a readable mapping`);
|
|
284
|
+
}
|
|
285
|
+
return parsed;
|
|
286
|
+
}
|
|
287
|
+
function rejectUnsafe(entryPath) {
|
|
288
|
+
throw new PackArchiveError("UNSAFE_PATH", `unsafe archive entry "${entryPath}" (symlink, non-file kind, or an unsafe or escaping path)`);
|
|
289
|
+
}
|
|
290
|
+
function rejectLimit(what) {
|
|
291
|
+
throw new PackArchiveError("LIMIT_EXCEEDED", `archive over a cap: ${what}`);
|
|
292
|
+
}
|
|
293
|
+
function invalidEnvelope(message) {
|
|
294
|
+
throw new PackArchiveError("ENVELOPE_INVALID", message);
|
|
213
295
|
}
|
|
214
296
|
function validateEnvelope(raw) {
|
|
215
|
-
if (!raw || typeof raw !== "object") {
|
|
216
|
-
|
|
297
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
298
|
+
return invalidEnvelope("malformed pack envelope (not a YAML mapping)");
|
|
217
299
|
}
|
|
218
300
|
const o = raw;
|
|
219
|
-
if (typeof o.formatVersion !== "number")
|
|
220
|
-
if (typeof o.name !== "string" || !o.name)
|
|
221
|
-
if (typeof o.version !== "string" || !o.version)
|
|
301
|
+
if (typeof o.formatVersion !== "number") invalidEnvelope("pack envelope: formatVersion must be a number");
|
|
302
|
+
if (typeof o.name !== "string" || !o.name) invalidEnvelope("pack envelope: name is required");
|
|
303
|
+
if (typeof o.version !== "string" || !o.version) invalidEnvelope("pack envelope: version is required");
|
|
222
304
|
if (typeof o.kind !== "string" || o.kind !== "declarative" && o.kind !== "code") {
|
|
223
|
-
|
|
305
|
+
invalidEnvelope('pack envelope: kind must be "declarative" or "code"');
|
|
306
|
+
}
|
|
307
|
+
if (typeof o.entry !== "string" || !o.entry) invalidEnvelope("pack envelope: entry is required");
|
|
308
|
+
if (o.digest !== void 0 && typeof o.digest !== "string") {
|
|
309
|
+
invalidEnvelope("pack envelope: digest must be a string (quote an all-digit digest)");
|
|
310
|
+
}
|
|
311
|
+
if (o.entryDigests !== void 0) {
|
|
312
|
+
const digests = o.entryDigests;
|
|
313
|
+
if (!digests || typeof digests !== "object" || Array.isArray(digests)) {
|
|
314
|
+
invalidEnvelope("pack envelope: entryDigests must be a mapping of path to digest");
|
|
315
|
+
}
|
|
316
|
+
for (const [entryPath, value] of Object.entries(digests)) {
|
|
317
|
+
if (typeof value !== "string") invalidEnvelope(`pack envelope: entryDigests["${entryPath}"] must be a string (quote an all-digit digest)`);
|
|
318
|
+
}
|
|
224
319
|
}
|
|
225
|
-
if (typeof o.entry !== "string" || !o.entry) throw new Error("pack envelope: entry is required");
|
|
226
320
|
const manifest = {
|
|
227
321
|
formatVersion: o.formatVersion,
|
|
228
322
|
name: o.name,
|
|
@@ -542,6 +636,9 @@ function declarativeEnvelope(name, version) {
|
|
|
542
636
|
""
|
|
543
637
|
].join("\n");
|
|
544
638
|
}
|
|
639
|
+
function releaseCore(version) {
|
|
640
|
+
return version.split(/[-+]/)[0];
|
|
641
|
+
}
|
|
545
642
|
function codeEnvelope(name, version) {
|
|
546
643
|
return [
|
|
547
644
|
"formatVersion: 1",
|
|
@@ -549,7 +646,7 @@ function codeEnvelope(name, version) {
|
|
|
549
646
|
`version: ${version}`,
|
|
550
647
|
"kind: code",
|
|
551
648
|
"entry: pack.cjs",
|
|
552
|
-
`minWaironVersion: ${SDK_VERSION}`,
|
|
649
|
+
`minWaironVersion: ${releaseCore(SDK_VERSION)}`,
|
|
553
650
|
""
|
|
554
651
|
].join("\n");
|
|
555
652
|
}
|
|
@@ -793,7 +890,7 @@ function buildPack(sourceDir) {
|
|
|
793
890
|
const manifest = parseManifest(decode(envelope.contents));
|
|
794
891
|
const identity = readInnerIdentity(files, manifest);
|
|
795
892
|
verifyIdentity(manifest, identity.name, identity.version);
|
|
796
|
-
const sealed = sealIntegrity(manifest, files, `@wairon/sdk@${SDK_VERSION}
|
|
893
|
+
const sealed = sealIntegrity(manifest, files, `@wairon/sdk@${SDK_VERSION}`);
|
|
797
894
|
const sealedText = serializeManifest(sealed);
|
|
798
895
|
const finalFiles = upsertEnvelope(files, sealedText);
|
|
799
896
|
const archiveBytes = assembleArchive(finalFiles);
|
|
@@ -801,10 +898,19 @@ function buildPack(sourceDir) {
|
|
|
801
898
|
const suggestedFileName = `${sealed.name}-${sealed.version}.wpack`;
|
|
802
899
|
return { archive: archiveBytes, info, suggestedFileName };
|
|
803
900
|
}
|
|
804
|
-
function
|
|
805
|
-
|
|
901
|
+
function listPackEntries(archive) {
|
|
902
|
+
try {
|
|
903
|
+
return listEntries(archive);
|
|
904
|
+
} catch (e) {
|
|
905
|
+
throw new PackArchiveError("NOT_A_PACK", `not a .wpack archive (unreadable ZIP: ${e instanceof Error ? e.message : String(e)})`);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function inspectArchive(archive, limits) {
|
|
909
|
+
const effectiveLimits = limits === void 0 ? defaultLimits() : limits;
|
|
910
|
+
const entries = listPackEntries(archive);
|
|
911
|
+
planExtraction(entries, effectiveLimits);
|
|
806
912
|
if (!entries.some((entry) => entry.path === ENVELOPE_FILENAME)) {
|
|
807
|
-
throw new
|
|
913
|
+
throw new PackArchiveError("NOT_A_PACK", "not a .wpack archive (missing wairon-pack.yaml envelope)");
|
|
808
914
|
}
|
|
809
915
|
const envelopeBytes = inflateEntry(archive, ENVELOPE_FILENAME);
|
|
810
916
|
const manifest = parseManifest(decode(envelopeBytes));
|
|
@@ -824,21 +930,27 @@ function inspectArchive(archive) {
|
|
|
824
930
|
if (manifest.minWaironVersion !== void 0) info.minWaironVersion = manifest.minWaironVersion;
|
|
825
931
|
return info;
|
|
826
932
|
}
|
|
827
|
-
function
|
|
933
|
+
function readPack(archive, limits) {
|
|
828
934
|
const effectiveLimits = limits === void 0 ? defaultLimits() : limits;
|
|
829
|
-
const entries =
|
|
935
|
+
const entries = listPackEntries(archive);
|
|
830
936
|
const plan = planExtraction(entries, effectiveLimits);
|
|
937
|
+
if (!plan.paths.includes(ENVELOPE_FILENAME)) {
|
|
938
|
+
throw new PackArchiveError("NOT_A_PACK", "not a .wpack archive (missing wairon-pack.yaml envelope)");
|
|
939
|
+
}
|
|
831
940
|
const files = [];
|
|
832
941
|
for (const approvedPath of plan.paths) {
|
|
833
942
|
const contents = inflateEntry(archive, approvedPath);
|
|
834
943
|
files.push({ path: approvedPath, contents });
|
|
835
944
|
}
|
|
836
945
|
const envelope = files.find((file) => file.path === ENVELOPE_FILENAME);
|
|
837
|
-
if (!envelope) {
|
|
838
|
-
throw new Error("not a .wpack archive (missing wairon-pack.yaml envelope)");
|
|
839
|
-
}
|
|
840
946
|
const manifest = parseManifest(decode(envelope.contents));
|
|
841
947
|
verifyIntegrity(manifest, files);
|
|
948
|
+
const packManifest = parseInnerManifest(manifest, files);
|
|
949
|
+
verifyIdentity(manifest, String(packManifest.name), String(packManifest.version));
|
|
950
|
+
return { manifest, packManifest, files };
|
|
951
|
+
}
|
|
952
|
+
function extractPack(archive, destDir, limits) {
|
|
953
|
+
const { manifest, files } = readPack(archive, limits);
|
|
842
954
|
const directory = path2.resolve(destDir);
|
|
843
955
|
writeTree(directory, files);
|
|
844
956
|
const result = {
|
|
@@ -983,8 +1095,14 @@ function scaffoldPack2(request) {
|
|
|
983
1095
|
function buildPack2(sourceDir) {
|
|
984
1096
|
return buildPack(sourceDir);
|
|
985
1097
|
}
|
|
986
|
-
function
|
|
987
|
-
return
|
|
1098
|
+
function packContentDigest(files) {
|
|
1099
|
+
return contentDigest(files);
|
|
1100
|
+
}
|
|
1101
|
+
function inspectArchive2(archive, limits) {
|
|
1102
|
+
return inspectArchive(archive, limits);
|
|
1103
|
+
}
|
|
1104
|
+
function readPack2(archive, limits) {
|
|
1105
|
+
return readPack(archive, limits);
|
|
988
1106
|
}
|
|
989
1107
|
function extractPack2(archive, destDir, limits) {
|
|
990
1108
|
return extractPack(archive, destDir, limits);
|
|
@@ -1000,6 +1118,7 @@ function extractTreeArchive2(archive, destDir, limits, refuseExecutableEntries)
|
|
|
1000
1118
|
}
|
|
1001
1119
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1002
1120
|
0 && (module.exports = {
|
|
1121
|
+
PackArchiveError,
|
|
1003
1122
|
buildPack,
|
|
1004
1123
|
buildTreeArchive,
|
|
1005
1124
|
defineRule,
|
|
@@ -1007,6 +1126,8 @@ function extractTreeArchive2(archive, destDir, limits, refuseExecutableEntries)
|
|
|
1007
1126
|
extractTreeArchive,
|
|
1008
1127
|
inspectArchive,
|
|
1009
1128
|
inspectTreeArchive,
|
|
1129
|
+
packContentDigest,
|
|
1130
|
+
readPack,
|
|
1010
1131
|
scaffoldPack
|
|
1011
1132
|
});
|
|
1012
1133
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/index.ts","../src/orchestrator.ts","../src/codec.ts","../src/treecodec.ts","../src/version.ts","../src/scaffold.ts","../src/archive.ts","../src/authoring.ts"],"sourcesContent":["{\n \"name\": \"@wairon/sdk\",\n \"version\": \"6.7.4-dev.1\",\n \"description\": \"Experimental: wairon pack-archive (.wpack) format authority and authoring toolkit — scaffold, build, inspect, and safely extract wairon extension packs.\",\n \"keywords\": [\n \"wairon\",\n \"sdd\",\n \"pack\",\n \"wpack\",\n \"archive\",\n \"developer-tools\",\n \"experimental\"\n ],\n \"author\": \"SYW\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/SYW-Apps/Waffle-AIron\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/SYW-Apps/Waffle-AIron.git\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"engines\": {\n \"node\": \"^22.23.4 || ^24.22.1 || >=26.12.1\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"clean\": \"rimraf dist\"\n },\n \"dependencies\": {\n \"fflate\": \"^0.8.2\",\n \"js-yaml\": \"^4.3.2\"\n },\n \"devDependencies\": {\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"^20.14.0\",\n \"rimraf\": \"^5.0.7\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.2\",\n \"vitest\": \"^4.1.9\"\n }\n}\n","import * as orchestrator from './orchestrator.js';\nimport type {\n PackArchiveInfo,\n PackBuildResult,\n PackExtractionLimits,\n PackExtractionResult,\n PackScaffoldRequest,\n TreeArchiveInfo,\n TreeBuildResult,\n TreeExtractionResult,\n TreeRootSource,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// SDK Portal (sdk_portal_impl) — the @wairon/sdk package entry. Each capability\n// is a 1:1 forward to the SDK orchestrator with no logic of its own; the module\n// also re-exports the pure pack-authoring value objects and the rule-authoring\n// contract (compile-time types + the defineRule helper).\n// ---------------------------------------------------------------------------\n\n/** Scaffold a new pack project (declarative or code) into a directory; returns the created file paths. */\nexport function scaffoldPack(request: PackScaffoldRequest): string[] {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.scaffoldPack(request);\n}\n\n/** Build an installable .wpack archive from a pack directory. */\nexport function buildPack(sourceDir: string): PackBuildResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.buildPack(sourceDir);\n}\n\n/** Inspect + verify a .wpack archive without extracting it. */\nexport function inspectArchive(archive: Uint8Array): PackArchiveInfo {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.inspectArchive(archive);\n}\n\n/** Safely extract a .wpack archive into a destination directory under enforced limits. */\nexport function extractPack(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n): PackExtractionResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.extractPack(archive, destDir, limits);\n}\n\n/** Pack a project's spec tree — the supplied roots' .wai directories — into a .waitree archive. */\nexport function buildTreeArchive(\n roots: TreeRootSource[],\n projectName: string,\n stateId?: string,\n includeDerived?: boolean,\n): TreeBuildResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.buildTreeArchive(roots, projectName, stateId, includeDerived);\n}\n\n/** Inspect a .waitree archive without extracting it. */\nexport function inspectTreeArchive(archive: Uint8Array): TreeArchiveInfo {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.inspectTreeArchive(archive);\n}\n\n/** Safely extract a .waitree archive into a destination project root under enforced limits. */\nexport function extractTreeArchive(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n refuseExecutableEntries?: boolean,\n): TreeExtractionResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.extractTreeArchive(archive, destDir, limits, refuseExecutableEntries);\n}\n\n// Re-export the pure pack-archive value objects...\nexport * from './types.js';\n// ...and the rule-authoring contract (SddRule + stable RuleContext/Finding facade + defineRule).\nexport * from './authoring.js';\n","import * as path from 'path';\nimport { load as yamlLoad } from 'js-yaml';\nimport * as codec from './codec.js';\nimport * as treecodec from './treecodec.js';\nimport * as scaffold from './scaffold.js';\nimport * as packArchive from './archive.js';\nimport { SDK_VERSION } from './version.js';\nimport type {\n PackArchiveInfo,\n PackArchiveManifest,\n PackBuildResult,\n PackExtractionLimits,\n PackExtractionResult,\n PackFile,\n PackScaffoldRequest,\n TreeArchiveInfo,\n TreeArchiveManifest,\n TreeBuildResult,\n TreeExtractionResult,\n TreeRootSource,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// SDK Orchestrator (sdk_orchestrator_impl) — the four pack workflows and the\n// three spec-tree archive workflows. Delegates format/safety decisions to the\n// codecs, template rendering to the pack scaffold, and all zip+fs I/O to\n// the archive adapter. Holds no state.\n//\n// Root DISCOVERY stays with the caller: the SDK never walks a spec tree, it\n// only archives the roots it is handed.\n// ---------------------------------------------------------------------------\n\nconst decode = (b: Uint8Array): string => new TextDecoder().decode(b);\nconst encode = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** Render the scaffold file map and write it under the target directory. */\nexport function scaffoldPack(request: PackScaffoldRequest): string[] {\n // Step 1: render the scaffold file map for the requested pack.\n const files = scaffold.render(request);\n // Step 2: write the rendered files as a directory tree under targetDir.\n packArchive.writeTree(request.targetDir, files);\n // Step 3: return the created file paths (targetDir-joined).\n return files.map((file) => path.join(request.targetDir, file.path));\n}\n\n/** Build an installable .wpack archive from a pack directory. */\nexport function buildPack(sourceDir: string): PackBuildResult {\n // Step 1: read the source pack directory into a file map.\n const files = packArchive.readPackDir(sourceDir);\n // Step 2: require an envelope.\n const envelope = files.find((file) => file.path === codec.ENVELOPE_FILENAME);\n if (!envelope) {\n // Step 3: reject a pack directory with no envelope.\n throw new Error('pack build requires a wairon-pack.yaml envelope (run `wairon pack init` to scaffold one)');\n }\n // Step 4 (parse): parse + validate the envelope (also version-gates the format).\n const manifest = codec.parseManifest(decode(envelope.contents));\n // Step 5: read the inner pack identity (pack.yaml, or package.json for code).\n const identity = readInnerIdentity(files, manifest);\n // Step 6: assert the envelope's name/version match the inner pack manifest.\n codec.verifyIdentity(manifest, identity.name, identity.version);\n // Step 7: seal integrity (entryDigests + digest + generatedBy/generatedAt).\n const sealed = codec.sealIntegrity(manifest, files, `@wairon/sdk@${SDK_VERSION}`, new Date().toISOString());\n // Step 8: serialize the sealed manifest back to canonical envelope text.\n const sealedText = codec.serializeManifest(sealed);\n // Step 9: upsert wairon-pack.yaml (sealed envelope text) into the file map.\n const finalFiles = upsertEnvelope(files, sealedText);\n // Step 10: deflate the files + envelope into .wpack archive bytes.\n const archiveBytes = packArchive.assembleArchive(finalFiles);\n // Step 11: assemble PackArchiveInfo + suggestedFileName.\n const info = buildInfo(sealed, finalFiles);\n const suggestedFileName = `${sealed.name}-${sealed.version}.wpack`;\n // Step 12: return the build result.\n return { archive: archiveBytes, info, suggestedFileName };\n}\n\n/** Inspect + verify a .wpack archive without extracting it. */\nexport function inspectArchive(archive: Uint8Array): PackArchiveInfo {\n // Step 1: enumerate archive entries without inflating.\n const entries = packArchive.listEntries(archive);\n // Step 2: is there no wairon-pack.yaml entry?\n if (!entries.some((entry) => entry.path === codec.ENVELOPE_FILENAME)) {\n // Step 3: reject a non-.wpack archive.\n throw new Error('not a .wpack archive (missing wairon-pack.yaml envelope)');\n }\n // Step 4 (readEnv): inflate just the envelope entry.\n const envelopeBytes = packArchive.inflateEntry(archive, codec.ENVELOPE_FILENAME);\n // Step 5: parse + version-check the envelope text.\n const manifest = codec.parseManifest(decode(envelopeBytes));\n // Step 6: compute compatibility against the running wairon version.\n const compatible = codec.checkCompatibility(manifest, SDK_VERSION);\n // Step 7: assemble PackArchiveInfo from the manifest + archive stats.\n const fileEntries = entries.filter((entry) => entry.kind === 'file');\n const totalUncompressedBytes = entries.reduce((sum, entry) => sum + entry.uncompressedSize, 0);\n const info: PackArchiveInfo = {\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n formatVersion: manifest.formatVersion,\n entryCount: fileEntries.length,\n totalUncompressedBytes,\n compatible,\n };\n if (manifest.minWaironVersion !== undefined) info.minWaironVersion = manifest.minWaironVersion;\n // Step 8: return the PackArchiveInfo (no extraction performed).\n return info;\n}\n\n/** Safely extract a .wpack archive into a destination directory under enforced limits. */\nexport function extractPack(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n): PackExtractionResult {\n // Step 1: did the caller omit limits?\n const effectiveLimits = limits === undefined\n // Step 2: fall back to the codec's default limit profile.\n ? codec.defaultLimits()\n : limits;\n // Step 3 (list): enumerate archive entries without inflating (caps run pre-decompress).\n const entries = packArchive.listEntries(archive);\n // Step 4: compute the safe extraction plan (throws on any unsafe/oversized entry).\n const plan = codec.planExtraction(entries, effectiveLimits);\n // Step 5: initialize an empty file list.\n const files: PackFile[] = [];\n // Step 6: inflate each approved path from the plan.\n for (const approvedPath of plan.paths) {\n // Step 7: inflate one approved entry.\n const contents = packArchive.inflateEntry(archive, approvedPath);\n // Step 8 (inflateEnd): append { path, contents } to the file list.\n files.push({ path: approvedPath, contents });\n }\n // Step 9: read the wairon-pack.yaml text from the inflated files.\n const envelope = files.find((file) => file.path === codec.ENVELOPE_FILENAME);\n if (!envelope) {\n throw new Error('not a .wpack archive (missing wairon-pack.yaml envelope)');\n }\n // Step 10: parse the envelope into the result manifest.\n const manifest = codec.parseManifest(decode(envelope.contents));\n // Step 11: enforce integrity BEFORE writing (throws on mismatch; no-op when none carried).\n codec.verifyIntegrity(manifest, files);\n // Step 12: write the approved, integrity-checked files as a directory tree.\n const directory = path.resolve(destDir);\n packArchive.writeTree(directory, files);\n // Step 13: assemble PackExtractionResult.\n const result: PackExtractionResult = {\n directory,\n entryPath: manifest.entry,\n manifest,\n name: manifest.name,\n kind: manifest.kind,\n entryCount: files.length,\n };\n // Step 14: return where the pack landed + its parsed manifest.\n return result;\n}\n\n// ── Spec-tree archive workflows (.waitree) ──────────────────────────────────\n\n/** Pack a project's spec tree — the supplied roots' .wai directories — into a .waitree. */\nexport function buildTreeArchive(\n roots: TreeRootSource[],\n projectName: string,\n stateId?: string,\n includeDerived?: boolean,\n): TreeBuildResult {\n // Step 1: initialize an empty archive file map and an empty packed-roots list.\n const files: PackFile[] = [];\n const packedRoots: string[] = [];\n // Step 2: pack each supplied root.\n for (const root of roots) {\n // Step 3: read this root's .wai directory recursively into a file map.\n const rootFiles = packArchive.readPackDir(root.waiDir);\n // Step 4: keep only portable design state.\n const portable = treecodec.selectTreeFiles(rootFiles, includeDerived === true);\n // Step 5 (packEnd): prefix with this root's project-relative path + '.wai/'.\n const prefix = treeRootPrefix(root.relativePath);\n for (const file of portable) files.push({ path: `${prefix}${file.path}`, contents: file.contents });\n packedRoots.push(normalizeRootPath(root.relativePath));\n }\n // Step 6: did the roots yield no files at all?\n if (files.length === 0) {\n // Step 7: an export that silently carries nothing is worse than a failure.\n throw new Error('tree export found no spec-tree files under the supplied roots');\n }\n // Step 8: build the unsealed envelope.\n const manifest: TreeArchiveManifest = {\n formatVersion: 1,\n projectName,\n roots: packedRoots,\n waironVersion: SDK_VERSION,\n includesDerived: includeDerived === true,\n };\n if (stateId !== undefined) manifest.stateId = stateId;\n // Step 9: seal integrity (entryDigests + digest + generatedBy/generatedAt).\n const sealed = treecodec.sealTreeIntegrity(\n manifest,\n files,\n `@wairon/sdk@${SDK_VERSION}`,\n new Date().toISOString(),\n );\n // Step 10: serialize the sealed manifest to canonical envelope text.\n const sealedText = treecodec.serializeTreeManifest(sealed);\n // Step 11: upsert wairon-tree.yaml (sealed envelope text) into the file map.\n const finalFiles: PackFile[] = [\n ...files.filter((file) => file.path !== treecodec.TREE_ENVELOPE_FILENAME),\n { path: treecodec.TREE_ENVELOPE_FILENAME, contents: encode(sealedText) },\n ];\n // Step 12: deflate the files + envelope into .waitree archive bytes.\n const archiveBytes = packArchive.assembleArchive(finalFiles);\n // Step 13: derive the suggested file name from the project name.\n const suggestedFileName = `${slugify(projectName)}.waitree`;\n // Step 14: return the build result.\n return { archive: archiveBytes, manifest: sealed, suggestedFileName, fileCount: files.length };\n}\n\n/** Inspect a .waitree archive without extracting it. */\nexport function inspectTreeArchive(archive: Uint8Array): TreeArchiveInfo {\n // Step 1: enumerate archive entries without inflating.\n const entries = packArchive.listEntries(archive);\n // Step 2: is there no wairon-tree.yaml entry?\n if (!entries.some((entry) => entry.path === treecodec.TREE_ENVELOPE_FILENAME)) {\n // Step 3: reject a non-.waitree archive.\n throw new Error('not a .waitree archive (missing wairon-tree.yaml envelope)');\n }\n // Step 4 (readEnv): inflate just the envelope entry.\n const envelopeBytes = packArchive.inflateEntry(archive, treecodec.TREE_ENVELOPE_FILENAME);\n // Step 5: parse + version-check the envelope text.\n const manifest = treecodec.parseTreeManifest(decode(envelopeBytes));\n // Step 6: compute compatibility against the running wairon version.\n const compatible = treecodec.checkTreeCompatibility(manifest, SDK_VERSION);\n // Step 7: assemble TreeArchiveInfo from the manifest + archive stats.\n const fileEntries = entries.filter((entry) => entry.kind === 'file');\n const totalUncompressedBytes = entries.reduce((sum, entry) => sum + entry.uncompressedSize, 0);\n // Step 8: return the TreeArchiveInfo (no extraction performed).\n return { manifest, entryCount: fileEntries.length, totalUncompressedBytes, compatible };\n}\n\n/** Safely extract a .waitree archive into a destination project root under enforced limits. */\nexport function extractTreeArchive(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n refuseExecutableEntries?: boolean,\n): TreeExtractionResult {\n // Step 1: did the caller omit limits?\n const effectiveLimits = limits === undefined\n // Step 2: fall back to the codec's tree limit profile.\n ? treecodec.defaultTreeLimits()\n : limits;\n // Step 3 (list): enumerate archive entries without inflating (caps run pre-decompress).\n const entries = packArchive.listEntries(archive);\n // Step 4: compute the safe extraction plan (throws on any unsafe/oversized entry).\n const plan = treecodec.planTreeExtraction(entries, effectiveLimits);\n // Step 5: did the caller ask for the over-the-wire portability guard?\n if (refuseExecutableEntries === true) {\n // Step 6: refuse executable or non-spec-tree entries before anything is inflated.\n treecodec.assertPortableTreePaths(plan.paths);\n }\n // Step 7 (inflate): initialize an empty file list.\n const files: PackFile[] = [];\n // Step 8: inflate each approved path from the plan.\n for (const approvedPath of plan.paths) {\n // Step 9: inflate one approved entry.\n const contents = packArchive.inflateEntry(archive, approvedPath);\n // Step 10 (inflateEnd): append { path, contents } to the file list.\n files.push({ path: approvedPath, contents });\n }\n // Step 11: is the wairon-tree.yaml envelope missing from the inflated files?\n const envelope = files.find((file) => file.path === treecodec.TREE_ENVELOPE_FILENAME);\n if (!envelope) {\n // Step 12: reject a non-.waitree archive.\n throw new Error('not a .waitree archive (missing wairon-tree.yaml envelope)');\n }\n // Step 13 (parse): parse the envelope into the result manifest.\n const manifest = treecodec.parseTreeManifest(decode(envelope.contents));\n // Step 14: enforce integrity BEFORE writing (throws on mismatch; no-op when none carried).\n treecodec.verifyTreeIntegrity(manifest, files);\n // Step 15: write the approved, integrity-checked files as a directory tree.\n const directory = path.resolve(destDir);\n packArchive.writeTree(directory, files);\n // Step 16: assemble TreeExtractionResult.\n const result: TreeExtractionResult = {\n destDir: directory,\n manifest,\n roots: manifest.roots,\n writtenPaths: files.map((file) => file.path),\n };\n // Step 17: return where the tree landed + its parsed manifest.\n return result;\n}\n\n// --- helpers ---------------------------------------------------------------\n\n/** The archive-path prefix for one packed root: '.wai/' at the top, else '<dir>/.wai/'. */\nfunction treeRootPrefix(relativePath: string): string {\n const normalized = normalizeRootPath(relativePath);\n return normalized === '.' ? '.wai/' : `${normalized}/.wai/`;\n}\n\n/** A packed root's canonical project-relative form: POSIX separators, '.' for the top root. */\nfunction normalizeRootPath(relativePath: string): string {\n const posix = relativePath.split(path.sep).join('/').replace(/^\\.\\//, '').replace(/\\/+$/, '');\n return posix === '' || posix === '.' ? '.' : posix;\n}\n\n/** A file-name-safe stem for a project name. */\nfunction slugify(projectName: string): string {\n const slug = projectName\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'spec-tree';\n}\n\nfunction readInnerIdentity(files: PackFile[], manifest: PackArchiveManifest): { name: string; version: string } {\n const innerPath = manifest.kind === 'code' ? 'package.json' : manifest.entry;\n const inner = files.find((file) => file.path === innerPath);\n if (!inner) throw new Error(`pack build: inner pack manifest \"${innerPath}\" is missing`);\n const parsed = (manifest.kind === 'code'\n ? JSON.parse(decode(inner.contents))\n : yamlLoad(decode(inner.contents))) as Record<string, unknown> | null;\n const name = parsed?.name;\n const version = parsed?.version;\n if (typeof name !== 'string' || typeof version !== 'string') {\n throw new Error(`pack build: inner pack manifest \"${innerPath}\" lacks a name/version`);\n }\n return { name, version };\n}\n\nfunction upsertEnvelope(files: PackFile[], envelopeText: string): PackFile[] {\n const others = files.filter((file) => file.path !== codec.ENVELOPE_FILENAME);\n return [...others, { path: codec.ENVELOPE_FILENAME, contents: encode(envelopeText) }];\n}\n\nfunction buildInfo(manifest: PackArchiveManifest, files: PackFile[]): PackArchiveInfo {\n const totalUncompressedBytes = files.reduce((sum, file) => sum + file.contents.length, 0);\n const info: PackArchiveInfo = {\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n formatVersion: manifest.formatVersion,\n entryCount: files.length,\n totalUncompressedBytes,\n compatible: true,\n };\n if (manifest.minWaironVersion !== undefined) info.minWaironVersion = manifest.minWaironVersion;\n return info;\n}\n","import { load as yamlLoad, dump as yamlDump } from 'js-yaml';\nimport { createHash } from 'crypto';\nimport type {\n ArchiveEntryMeta,\n PackArchiveManifest,\n PackExtractionLimits,\n PackExtractionPlan,\n PackFile,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Pack Codec (pack_codec_impl) — PURE format + safety logic, no I/O.\n//\n// planExtraction is the single safety chokepoint (zip-slip / size / ratio /\n// depth / symlink guards, all pre-decompress). sealIntegrity/verifyIntegrity\n// are the produce/verify integrity pair. The codec stays pure: build time is\n// passed in, never read here.\n// ---------------------------------------------------------------------------\n\n/** The archive-root envelope filename. */\nexport const ENVELOPE_FILENAME = 'wairon-pack.yaml';\n\n/** The highest pack-archive format major this SDK understands. */\nconst SUPPORTED_FORMAT_VERSION = 1;\n\n/** The default extraction-safety profile: 4096 / 32 MiB / 8 MiB / 100:1 / depth 16. */\nconst DEFAULTS = {\n maxEntries: 4096,\n maxTotalUncompressedBytes: 32 * 1024 * 1024,\n maxEntryBytes: 8 * 1024 * 1024,\n maxCompressionRatio: 100,\n maxDepth: 16,\n} as const;\n\n/** Parse + validate the envelope text into a PackArchiveManifest; throws on malformed/newer-major. */\nexport function parseManifest(text: string): PackArchiveManifest {\n // Step 1: parse the envelope YAML text (throws on malformed YAML).\n const raw = yamlLoad(text);\n // Step 2: validate the required fields are present and well-typed.\n const manifest = validateEnvelope(raw);\n // Step 3: is the format major newer than this wairon supports?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: fail loudly rather than silently mis-read a newer format.\n throw new Error('unsupported pack-archive formatVersion (newer than this wairon understands)');\n }\n // Step 5: return the parsed manifest.\n return manifest;\n}\n\n/** Serialize a manifest to canonical wairon-pack.yaml text (build path). */\nexport function serializeManifest(manifest: PackArchiveManifest): string {\n // Step 1: drop undefined optional fields for a clean, canonical envelope.\n const clean: Record<string, unknown> = {\n formatVersion: manifest.formatVersion,\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n };\n if (manifest.minWaironVersion !== undefined) clean.minWaironVersion = manifest.minWaironVersion;\n if (manifest.digest !== undefined) clean.digest = manifest.digest;\n if (manifest.entryDigests !== undefined) clean.entryDigests = manifest.entryDigests;\n if (manifest.generatedBy !== undefined) clean.generatedBy = manifest.generatedBy;\n if (manifest.generatedAt !== undefined) clean.generatedAt = manifest.generatedAt;\n // Step 2: return the wairon-pack.yaml text.\n return yamlDump(clean, { sortKeys: false });\n}\n\n/** The default extraction-safety profile; callers override individual caps. */\nexport function defaultLimits(): PackExtractionLimits {\n // Step 1: return the default caps profile.\n return { ...DEFAULTS };\n}\n\n/** Compute the safe extraction plan from enumerated entries under `limits`, or throw. */\nexport function planExtraction(entries: ArchiveEntryMeta[], limits: PackExtractionLimits): PackExtractionPlan {\n // Step 1: resolve effective caps — each field of `limits` over the defaults.\n const caps = {\n maxEntries: limits.maxEntries ?? DEFAULTS.maxEntries,\n maxTotalUncompressedBytes: limits.maxTotalUncompressedBytes ?? DEFAULTS.maxTotalUncompressedBytes,\n maxEntryBytes: limits.maxEntryBytes ?? DEFAULTS.maxEntryBytes,\n maxCompressionRatio: limits.maxCompressionRatio ?? DEFAULTS.maxCompressionRatio,\n maxDepth: limits.maxDepth ?? DEFAULTS.maxDepth,\n };\n // Step 2: initialize an empty approved-path list and a running total of 0.\n const approved: string[] = [];\n let total = 0;\n // Step 3: vet each enumerated entry.\n for (const entry of entries) {\n // Step 4: reject symlinks/non-regular entries and structurally unsafe paths.\n if (isSymlinkOrNonRegular(entry.kind) || isStructurallyUnsafePath(entry.path)) {\n rejectUnsafe();\n }\n // Directory entries are structural (writeTree recreates them from file\n // paths) — skip without approving, never inflate a 0-byte dir marker.\n if (entry.kind === 'dir') continue;\n // Step 5: normalize the entry path to a destination-relative POSIX path.\n const normalized = normalizeRelPath(entry.path);\n // Step 6: reject zip-slip and over-deep paths.\n if (escapesDestination(normalized) || pathDepth(normalized) > caps.maxDepth) {\n rejectUnsafe();\n }\n // Step 7: reject oversized entries and zip bombs.\n if (entry.uncompressedSize > caps.maxEntryBytes || compressionRatio(entry) > caps.maxCompressionRatio) {\n rejectUnsafe();\n }\n // Step 8 (vetEnd): accept — append the path and add its inflated size.\n approved.push(normalized);\n total += entry.uncompressedSize;\n }\n // Step 9: reject archives exceeding the aggregate caps.\n if (approved.length > caps.maxEntries || total > caps.maxTotalUncompressedBytes) {\n rejectUnsafe();\n }\n // Step 11: return the approved plan.\n return { paths: approved, totalUncompressedBytes: total };\n}\n\n/** Assert the envelope's name/version match the inner pack manifest; throw on mismatch. */\nexport function verifyIdentity(manifest: PackArchiveManifest, packName: string, packVersion: string): void {\n // Step 1: do envelope name/version differ from the inner pack manifest?\n if (manifest.name !== packName || manifest.version !== packVersion) {\n // Step 2: reject a tampered/mis-assembled archive.\n throw new Error('envelope identity mismatch (envelope name/version differ from the inner pack manifest)');\n }\n // Step 3: identity verified.\n}\n\n/** Verify every entry's sha256 against entryDigests; false when none carried, throws on mismatch. */\nexport function verifyIntegrity(manifest: PackArchiveManifest, files: PackFile[]): boolean {\n // Step 1: did the envelope carry no integrity data?\n if (!manifest.entryDigests) {\n // Step 2: no integrity data present — return false.\n return false;\n }\n const digests = manifest.entryDigests;\n // Step 3: check each file's digest.\n for (const file of files) {\n // The envelope carries these digests and cannot digest itself — skip it.\n if (file.path === ENVELOPE_FILENAME) continue;\n // Step 4: does the recomputed sha256 differ from the recorded digest?\n if (sha256(file.contents) !== digests[file.path]) {\n // Step 7: a digest mismatch means tampering.\n throw new Error('integrity digest mismatch');\n }\n // Step 5 (checkEnd): this file's digest matches.\n }\n // Step 6: all digests matched — return true.\n return true;\n}\n\n/** Produce-side partner of verifyIntegrity: fill entryDigests + digest + stamps. */\nexport function sealIntegrity(\n manifest: PackArchiveManifest,\n files: PackFile[],\n generatedBy: string,\n generatedAt: string,\n): PackArchiveManifest {\n // Step 1: initialize an empty entryDigests map.\n const entryDigests: Record<string, string> = {};\n // Step 2: hash each file.\n for (const file of files) {\n // The envelope is the carrier of these digests — never hash it into itself.\n if (file.path === ENVELOPE_FILENAME) continue;\n // Step 3 (hashEnd): compute sha256(file.contents) and record it under file.path.\n entryDigests[file.path] = sha256(file.contents);\n }\n // Step 4: compute an overall manifest digest over the sorted entryDigests.\n const digest = sha256(canonicalDigestBytes(entryDigests));\n // Step 5: set entryDigests, digest, generatedBy, generatedAt.\n // Step 6: return the sealed manifest.\n return { ...manifest, entryDigests, digest, generatedBy, generatedAt };\n}\n\n/** Whether the archive's formatVersion + minWaironVersion are compatible with `waironVersion`. */\nexport function checkCompatibility(manifest: PackArchiveManifest, waironVersion: string): boolean {\n // Step 1: is the archive format unsupported?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: incompatible.\n return false;\n }\n // Step 2: is the running wairon below the pack's minimum?\n if (manifest.minWaironVersion && isBelow(waironVersion, manifest.minWaironVersion)) {\n // Step 4: incompatible.\n return false;\n }\n // Step 3: compatible.\n return true;\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction rejectUnsafe(): never {\n throw new Error('reject: unsafe or oversized archive entry (zip-slip / size / ratio / depth guard)');\n}\n\nfunction validateEnvelope(raw: unknown): PackArchiveManifest {\n if (!raw || typeof raw !== 'object') {\n throw new Error('malformed pack envelope (not a YAML mapping)');\n }\n const o = raw as Record<string, unknown>;\n if (typeof o.formatVersion !== 'number') throw new Error('pack envelope: formatVersion must be a number');\n if (typeof o.name !== 'string' || !o.name) throw new Error('pack envelope: name is required');\n if (typeof o.version !== 'string' || !o.version) throw new Error('pack envelope: version is required');\n if (typeof o.kind !== 'string' || (o.kind !== 'declarative' && o.kind !== 'code')) {\n throw new Error('pack envelope: kind must be \"declarative\" or \"code\"');\n }\n if (typeof o.entry !== 'string' || !o.entry) throw new Error('pack envelope: entry is required');\n const manifest: PackArchiveManifest = {\n formatVersion: o.formatVersion,\n name: o.name,\n version: o.version,\n kind: o.kind,\n entry: o.entry,\n };\n if (typeof o.minWaironVersion === 'string') manifest.minWaironVersion = o.minWaironVersion;\n if (typeof o.digest === 'string') manifest.digest = o.digest;\n if (o.entryDigests && typeof o.entryDigests === 'object') {\n manifest.entryDigests = o.entryDigests as Record<string, string>;\n }\n if (typeof o.generatedBy === 'string') manifest.generatedBy = o.generatedBy;\n if (typeof o.generatedAt === 'string') manifest.generatedAt = o.generatedAt;\n return manifest;\n}\n\nfunction isSymlinkOrNonRegular(kind: string): boolean {\n return kind !== 'file' && kind !== 'dir';\n}\n\nfunction isStructurallyUnsafePath(p: string): boolean {\n if (p.includes('\\\\')) return true; // backslash\n if (/^[A-Za-z]:/.test(p)) return true; // drive letter\n if (p.startsWith('/')) return true; // absolute POSIX\n return p.split('/').some((seg) => seg === '..'); // parent traversal\n}\n\nfunction normalizeRelPath(p: string): string {\n return p\n .split('/')\n .filter((seg) => seg !== '' && seg !== '.')\n .join('/');\n}\n\nfunction escapesDestination(normalized: string): boolean {\n return normalized.startsWith('/') || normalized.split('/').some((seg) => seg === '..');\n}\n\nfunction pathDepth(normalized: string): number {\n return normalized.split('/').filter((seg) => seg !== '').length;\n}\n\nfunction compressionRatio(entry: ArchiveEntryMeta): number {\n if (entry.compressedSize > 0) return entry.uncompressedSize / entry.compressedSize;\n return entry.uncompressedSize > 0 ? Infinity : 0;\n}\n\nfunction canonicalDigestBytes(entryDigests: Record<string, string>): Uint8Array {\n const lines = Object.keys(entryDigests)\n .sort()\n .map((key) => `${key}:${entryDigests[key]}`)\n .join('\\n');\n return new TextEncoder().encode(lines);\n}\n\nfunction sha256(data: Uint8Array): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\nfunction isBelow(running: string, minimum: string): boolean {\n const [rMaj, rMin, rPat] = parseSemverCore(running);\n const [mMaj, mMin, mPat] = parseSemverCore(minimum);\n if (rMaj !== mMaj) return rMaj < mMaj;\n if (rMin !== mMin) return rMin < mMin;\n return rPat < mPat;\n}\n\nfunction parseSemverCore(v: string): [number, number, number] {\n const cleaned = v.trim().replace(/^[^0-9]*/, ''); // strip leading ^, ~, >=, v, etc.\n const core = cleaned.split(/[-+]/)[0]; // drop prerelease/build metadata\n const parts = core.split('.').map((n) => parseInt(n, 10));\n return [parts[0] || 0, parts[1] || 0, parts[2] || 0];\n}\n","import { load as yamlLoad, dump as yamlDump } from 'js-yaml';\nimport { createHash } from 'crypto';\nimport type {\n ArchiveEntryMeta,\n PackExtractionLimits,\n PackExtractionPlan,\n PackFile,\n TreeArchiveManifest,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Tree Codec (tree_codec_impl) — PURE format + safety logic for the `.waitree`\n// spec-tree archive, no I/O and no clock.\n//\n// selectTreeFiles is the single portability decision (what belongs in a tree\n// archive at all); planTreeExtraction is the single pre-decompress safety\n// chokepoint; assertPortableTreePaths is the over-the-wire executable guard;\n// sealTreeIntegrity/verifyTreeIntegrity are the produce/verify pair.\n//\n// The small pure path/digest helpers below deliberately mirror the pack codec's\n// rather than importing them: tree_codec declares NO dependencies, and reaching\n// into pack_codec for them would make one codec depend on the other for a\n// handful of one-line functions.\n// ---------------------------------------------------------------------------\n\n/** The tree-archive envelope filename. */\nexport const TREE_ENVELOPE_FILENAME = 'wairon-tree.yaml';\n\n/** The highest tree-archive format major this SDK understands. */\nconst SUPPORTED_FORMAT_VERSION = 1;\n\n/**\n * The tree caps profile: looser than the pack profile on entry count and total\n * size (a real spec tree is thousands of small YAML files across several\n * chained roots) and stricter on nothing.\n */\nconst TREE_DEFAULTS = {\n maxEntries: 20000,\n maxTotalUncompressedBytes: 64 * 1024 * 1024,\n maxEntryBytes: 8 * 1024 * 1024,\n maxCompressionRatio: 100,\n maxDepth: 24,\n} as const;\n\n/** Root-relative directories holding REGENERABLE artifacts — never portable design state. */\nconst DERIVED_ROOTS = ['generated', 'docs'];\n\n/** Executable extensions: a bundled code pack's entry can ride inside a tree. */\nconst EXECUTABLE_EXT_RE = /\\.(c|m)?js$/i;\n\n/** The directory every packed root's content lives under, inside the archive. */\nconst WAI_SEGMENT = '.wai';\n\n/** Parse + validate the envelope text into a TreeArchiveManifest; throws on malformed/newer-major. */\nexport function parseTreeManifest(text: string): TreeArchiveManifest {\n // Step 1: parse the envelope YAML text (throws on malformed YAML).\n const raw = yamlLoad(text);\n // Step 2: validate the required fields are present and well-typed.\n const manifest = validateEnvelope(raw);\n // Step 3: is the format major newer than this wairon supports?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: fail loudly rather than silently mis-read a newer format.\n throw new Error('unsupported tree-archive formatVersion (newer than this wairon understands)');\n }\n // Step 5: return the parsed manifest.\n return manifest;\n}\n\n/** Serialize a manifest to canonical wairon-tree.yaml text (export path). */\nexport function serializeTreeManifest(manifest: TreeArchiveManifest): string {\n // Step 1: drop undefined optional fields for a clean, canonical envelope.\n const clean: Record<string, unknown> = {\n formatVersion: manifest.formatVersion,\n projectName: manifest.projectName,\n roots: manifest.roots,\n };\n if (manifest.stateId !== undefined) clean.stateId = manifest.stateId;\n if (manifest.waironVersion !== undefined) clean.waironVersion = manifest.waironVersion;\n if (manifest.minWaironVersion !== undefined) clean.minWaironVersion = manifest.minWaironVersion;\n if (manifest.includesDerived !== undefined) clean.includesDerived = manifest.includesDerived;\n if (manifest.digest !== undefined) clean.digest = manifest.digest;\n if (manifest.entryDigests !== undefined) clean.entryDigests = manifest.entryDigests;\n if (manifest.generatedBy !== undefined) clean.generatedBy = manifest.generatedBy;\n if (manifest.generatedAt !== undefined) clean.generatedAt = manifest.generatedAt;\n // Step 2: return the wairon-tree.yaml text.\n return yamlDump(clean, { sortKeys: false });\n}\n\n/** The tree extraction-safety profile; callers override individual caps. */\nexport function defaultTreeLimits(): PackExtractionLimits {\n // Step 1: return the tree caps profile.\n return { ...TREE_DEFAULTS };\n}\n\n/**\n * Decide which of a root's files are portable design state: keep authored spec\n * state, drop regenerable artifacts unless the caller asked for them. Paths are\n * relative to the root's `.wai/` directory.\n */\nexport function selectTreeFiles(files: PackFile[], includeDerived: boolean): PackFile[] {\n // Step 1: did the caller ask for regenerable artifacts too?\n if (includeDerived) {\n // Step 2: return the file map unchanged — an explicit full-fidelity archive.\n return files;\n }\n // Step 3: drop every file under a regenerable root — a moved tree carries the\n // design, not its rendered output, which the destination regenerates.\n const kept = files.filter((file) => !isDerivedPath(file.path));\n // Step 4: return the portable design state.\n return kept;\n}\n\n/** Compute the safe extraction plan from enumerated entries under `limits`, or throw. */\nexport function planTreeExtraction(entries: ArchiveEntryMeta[], limits: PackExtractionLimits): PackExtractionPlan {\n // Step 1: resolve effective caps — each field of `limits` over the tree defaults.\n const caps = {\n maxEntries: limits.maxEntries ?? TREE_DEFAULTS.maxEntries,\n maxTotalUncompressedBytes: limits.maxTotalUncompressedBytes ?? TREE_DEFAULTS.maxTotalUncompressedBytes,\n maxEntryBytes: limits.maxEntryBytes ?? TREE_DEFAULTS.maxEntryBytes,\n maxCompressionRatio: limits.maxCompressionRatio ?? TREE_DEFAULTS.maxCompressionRatio,\n maxDepth: limits.maxDepth ?? TREE_DEFAULTS.maxDepth,\n };\n // Step 2: initialize an empty approved-path list and a running total of 0.\n const approved: string[] = [];\n let total = 0;\n // Step 3: vet each enumerated entry.\n for (const entry of entries) {\n // Step 4: reject symlinks/non-regular entries and structurally unsafe paths.\n if (isSymlinkOrNonRegular(entry.kind) || isStructurallyUnsafePath(entry.path)) {\n rejectUnsafe();\n }\n // Directory entries are structural (writeTree recreates them from file\n // paths) — skip without approving, never inflate a 0-byte dir marker.\n if (entry.kind === 'dir') continue;\n // Step 5: normalize the entry path to a destination-relative POSIX path.\n const normalized = normalizeRelPath(entry.path);\n // Step 6: reject zip-slip and over-deep paths.\n if (escapesDestination(normalized) || pathDepth(normalized) > caps.maxDepth) {\n rejectUnsafe();\n }\n // Step 7: reject oversized entries and zip bombs.\n if (entry.uncompressedSize > caps.maxEntryBytes || compressionRatio(entry) > caps.maxCompressionRatio) {\n rejectUnsafe();\n }\n // Step 8 (vetEnd): accept — append the path and add its inflated size.\n approved.push(normalized);\n total += entry.uncompressedSize;\n }\n // Step 9: reject archives exceeding the aggregate caps.\n if (approved.length > caps.maxEntries || total > caps.maxTotalUncompressedBytes) {\n rejectUnsafe();\n }\n // Step 11: return the approved plan.\n return { paths: approved, totalUncompressedBytes: total };\n}\n\n/**\n * Assert the planned paths carry no executable content and nothing outside a\n * spec-tree root. Called by any surface accepting an archive over the wire; a\n * local extraction on the developer's own machine may skip it.\n */\nexport function assertPortableTreePaths(paths: string[]): void {\n // Step 1: check each planned path.\n for (const entryPath of paths) {\n // Step 2: is this an executable file (a bundled code pack's entry)?\n if (EXECUTABLE_EXT_RE.test(entryPath)) {\n // Step 6 (rejectExecutable): same guidance the pack surface gives.\n throw new Error(\n 'refused: the archive carries executable content. Only declarative spec state transfers over this ' +\n 'surface; rule/code packs are executable and install via the trusted filesystem (mount into ' +\n 'WAIRON_PACKS_DIR, or run `wairon packs add`).',\n );\n }\n // Step 3: does the path sit outside any recognized spec-tree root?\n if (entryPath !== TREE_ENVELOPE_FILENAME && !isUnderWaiRoot(entryPath)) {\n // Step 7 (rejectForeign): a tree archive carries .wai trees, never arbitrary project files.\n throw new Error(`refused: the archive carries an entry outside any spec-tree root (\"${entryPath}\")`);\n }\n // Step 4 (checkEnd): this path is portable spec-tree content.\n }\n // Step 5: every path is portable.\n}\n\n/** Verify every entry's sha256 against entryDigests; false when none carried, throws on mismatch. */\nexport function verifyTreeIntegrity(manifest: TreeArchiveManifest, files: PackFile[]): boolean {\n // Step 1: did the envelope carry no integrity data?\n if (!manifest.entryDigests) {\n // Step 2: no integrity data present — return false.\n return false;\n }\n const digests = manifest.entryDigests;\n // Step 3: check each file's digest.\n for (const file of files) {\n // The envelope carries these digests and cannot digest itself — skip it.\n if (file.path === TREE_ENVELOPE_FILENAME) continue;\n // Step 4: does the recomputed sha256 differ from the recorded digest?\n if (sha256(file.contents) !== digests[file.path]) {\n // Step 7: a digest mismatch means tampering.\n throw new Error('tree integrity digest mismatch');\n }\n // Step 5 (checkEnd): this file's digest matches.\n }\n // Step 6: all digests matched — return true.\n return true;\n}\n\n/** Produce-side partner of verifyTreeIntegrity: fill entryDigests + digest + stamps. */\nexport function sealTreeIntegrity(\n manifest: TreeArchiveManifest,\n files: PackFile[],\n generatedBy: string,\n generatedAt: string,\n): TreeArchiveManifest {\n // Step 1: initialize an empty entryDigests map.\n const entryDigests: Record<string, string> = {};\n // Step 2: hash each file.\n for (const file of files) {\n // The envelope is the carrier of these digests — never hash it into itself.\n if (file.path === TREE_ENVELOPE_FILENAME) continue;\n // Step 3 (hashEnd): compute sha256(file.contents) and record it under file.path.\n entryDigests[file.path] = sha256(file.contents);\n }\n // Step 4: compute an overall manifest digest over the sorted entryDigests.\n const digest = sha256(canonicalDigestBytes(entryDigests));\n // Step 5: set entryDigests, digest, generatedBy, generatedAt.\n // Step 6: return the sealed manifest.\n return { ...manifest, entryDigests, digest, generatedBy, generatedAt };\n}\n\n/** Whether the archive's formatVersion + minWaironVersion are compatible with `waironVersion`. */\nexport function checkTreeCompatibility(manifest: TreeArchiveManifest, waironVersion: string): boolean {\n // Step 1: is the archive format unsupported?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: incompatible.\n return false;\n }\n // Step 2: is the running wairon below the archive's minimum?\n if (manifest.minWaironVersion && isBelow(waironVersion, manifest.minWaironVersion)) {\n // Step 4: incompatible.\n return false;\n }\n // Step 3: compatible.\n return true;\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction rejectUnsafe(): never {\n throw new Error('reject: unsafe or oversized tree-archive entry (zip-slip / size / ratio / depth guard)');\n}\n\nfunction validateEnvelope(raw: unknown): TreeArchiveManifest {\n if (!raw || typeof raw !== 'object') {\n throw new Error('malformed tree envelope (not a YAML mapping)');\n }\n const o = raw as Record<string, unknown>;\n if (typeof o.formatVersion !== 'number') throw new Error('tree envelope: formatVersion must be a number');\n if (typeof o.projectName !== 'string' || !o.projectName) throw new Error('tree envelope: projectName is required');\n if (!Array.isArray(o.roots) || o.roots.length === 0 || o.roots.some((r) => typeof r !== 'string' || !r)) {\n throw new Error('tree envelope: roots must be a non-empty list of project-relative directories');\n }\n const manifest: TreeArchiveManifest = {\n formatVersion: o.formatVersion,\n projectName: o.projectName,\n roots: o.roots as string[],\n };\n if (typeof o.stateId === 'string') manifest.stateId = o.stateId;\n if (typeof o.waironVersion === 'string') manifest.waironVersion = o.waironVersion;\n if (typeof o.minWaironVersion === 'string') manifest.minWaironVersion = o.minWaironVersion;\n if (typeof o.includesDerived === 'boolean') manifest.includesDerived = o.includesDerived;\n if (typeof o.digest === 'string') manifest.digest = o.digest;\n if (o.entryDigests && typeof o.entryDigests === 'object') {\n manifest.entryDigests = o.entryDigests as Record<string, string>;\n }\n if (typeof o.generatedBy === 'string') manifest.generatedBy = o.generatedBy;\n if (typeof o.generatedAt === 'string') manifest.generatedAt = o.generatedAt;\n return manifest;\n}\n\n/** True for a path under a regenerable root, relative to a root's .wai/ directory. */\nfunction isDerivedPath(relPath: string): boolean {\n const first = relPath.split('/')[0];\n return DERIVED_ROOTS.includes(first);\n}\n\n/** True when an archive path lives under some root's .wai/ directory. */\nfunction isUnderWaiRoot(archivePath: string): boolean {\n const segments = archivePath.split('/');\n // The .wai segment must exist AND carry content beneath it — a bare '.wai'\n // entry names a directory, not spec-tree state.\n const at = segments.indexOf(WAI_SEGMENT);\n return at >= 0 && at < segments.length - 1;\n}\n\nfunction isSymlinkOrNonRegular(kind: string): boolean {\n return kind !== 'file' && kind !== 'dir';\n}\n\nfunction isStructurallyUnsafePath(p: string): boolean {\n if (p.includes('\\\\')) return true; // backslash\n if (/^[A-Za-z]:/.test(p)) return true; // drive letter\n if (p.startsWith('/')) return true; // absolute POSIX\n return p.split('/').some((seg) => seg === '..'); // parent traversal\n}\n\nfunction normalizeRelPath(p: string): string {\n return p\n .split('/')\n .filter((seg) => seg !== '' && seg !== '.')\n .join('/');\n}\n\nfunction escapesDestination(normalized: string): boolean {\n return normalized.startsWith('/') || normalized.split('/').some((seg) => seg === '..');\n}\n\nfunction pathDepth(normalized: string): number {\n return normalized.split('/').filter((seg) => seg !== '').length;\n}\n\nfunction compressionRatio(entry: ArchiveEntryMeta): number {\n if (entry.compressedSize > 0) return entry.uncompressedSize / entry.compressedSize;\n return entry.uncompressedSize > 0 ? Infinity : 0;\n}\n\nfunction canonicalDigestBytes(entryDigests: Record<string, string>): Uint8Array {\n const lines = Object.keys(entryDigests)\n .sort()\n .map((key) => `${key}:${entryDigests[key]}`)\n .join('\\n');\n return new TextEncoder().encode(lines);\n}\n\nfunction sha256(data: Uint8Array): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\nfunction isBelow(running: string, minimum: string): boolean {\n const [rMaj, rMin, rPat] = parseSemverCore(running);\n const [mMaj, mMin, mPat] = parseSemverCore(minimum);\n if (rMaj !== mMaj) return rMaj < mMaj;\n if (rMin !== mMin) return rMin < mMin;\n return rPat < mPat;\n}\n\nfunction parseSemverCore(v: string): [number, number, number] {\n const cleaned = v.trim().replace(/^[^0-9]*/, ''); // strip leading ^, ~, >=, v, etc.\n const core = cleaned.split(/[-+]/)[0]; // drop prerelease/build metadata\n const parts = core.split('.').map((n) => parseInt(n, 10));\n return [parts[0] || 0, parts[1] || 0, parts[2] || 0];\n}\n","// The running @wairon/sdk version — stamped into built archives (generatedBy)\n// and used as the \"running wairon version\" for pack version-compatibility\n// checks. tsup inlines package.json at build time; at runtime the require\n// resolves against the shipped package (../package.json from dist/).\n\nexport const SDK_VERSION: string = loadVersion();\n\nfunction loadVersion(): string {\n try {\n const pkg = require('../package.json') as { version?: string };\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n","import type { PackFile, PackScaffoldRequest } from './types.js';\nimport { SDK_VERSION } from './version.js';\n\n// ---------------------------------------------------------------------------\n// Pack Scaffold (pack_scaffold_impl) — PURE template rendering for\n// `wairon pack init`. Produces an in-memory file map; writes nothing. Code\n// packs pin @wairon/sdk to the running SDK version.\n// ---------------------------------------------------------------------------\n\nconst enc = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** Render the scaffold file map for the requested pack (declarative or code). */\nexport function render(request: PackScaffoldRequest): PackFile[] {\n const version = request.version ?? '0.1.0';\n let files: PackFile[];\n // Step 1: which variant?\n if (request.kind === 'code') {\n // Step 2: render the code-pack file map.\n files = renderCodePack(request.name, version);\n // Step 3: skip the declarative variant (fall through to the skill gate).\n } else {\n // Step 4 (declVariant): render the declarative-pack file map.\n files = renderDeclarativePack(request.name, version);\n }\n // Step 5 (skillGate): include a skill stub?\n if (request.withSkill) {\n // Step 6: append a skills/<id>/SKILL.md stub to the file map.\n files.push(renderSkillStub(request.name, version));\n }\n // Step 7 (done): return the rendered file map.\n return files;\n}\n\n// --- variant renderers -----------------------------------------------------\n\nfunction renderDeclarativePack(name: string, version: string): PackFile[] {\n return [\n { path: 'wairon-pack.yaml', contents: enc(declarativeEnvelope(name, version)) },\n { path: 'pack.yaml', contents: enc(declarativeManifest(name, version)) },\n { path: 'README.md', contents: enc(readme(name, 'declarative', 'pack.yaml')) },\n ];\n}\n\nfunction renderCodePack(name: string, version: string): PackFile[] {\n return [\n { path: 'wairon-pack.yaml', contents: enc(codeEnvelope(name, version)) },\n { path: 'package.json', contents: enc(codePackageJson(name, version)) },\n { path: 'tsconfig.json', contents: enc(codeTsconfig()) },\n { path: 'pack.ts', contents: enc(codeEntry(name, version)) },\n { path: 'README.md', contents: enc(readme(name, 'code', 'pack.cjs')) },\n ];\n}\n\nfunction renderSkillStub(name: string, _version: string): PackFile {\n const id = slug(name);\n return { path: `skills/${id}/SKILL.md`, contents: enc(skillStub(name)) };\n}\n\n// --- templates -------------------------------------------------------------\n\nfunction declarativeEnvelope(name: string, version: string): string {\n return [\n 'formatVersion: 1',\n `name: ${name}`,\n `version: ${version}`,\n 'kind: declarative',\n 'entry: pack.yaml',\n '',\n ].join('\\n');\n}\n\nfunction codeEnvelope(name: string, version: string): string {\n return [\n 'formatVersion: 1',\n `name: ${name}`,\n `version: ${version}`,\n 'kind: code',\n 'entry: pack.cjs',\n `minWaironVersion: ${SDK_VERSION}`,\n '',\n ].join('\\n');\n}\n\nfunction declarativeManifest(name: string, version: string): string {\n return [\n `name: ${name}`,\n `version: ${version}`,\n '',\n '# Custom architectural profiles this pack contributes (example, commented):',\n '# profiles:',\n '# my-profile:',\n '# family: backend-like',\n '# forbiddenStereotypes:',\n '# - types: [Adapter]',\n '# reason: \"Domain components must not touch adapters directly.\"',\n 'profiles: {}',\n '',\n '# Target language / platform tables (example, commented):',\n '# languages:',\n '# rust:',\n '# unsupportedFlow: {}',\n 'languages: {}',\n '',\n '# Reusable, versioned architecture patterns:',\n 'patterns: []',\n '',\n ].join('\\n');\n}\n\nfunction codePackageJson(name: string, version: string): string {\n const pkg = {\n name,\n version,\n private: true,\n scripts: {\n build: 'esbuild pack.ts --bundle --platform=node --packages=external --format=cjs --outfile=pack.cjs',\n },\n dependencies: {\n '@wairon/sdk': SDK_VERSION,\n },\n devDependencies: {\n esbuild: '^0.21.0',\n typescript: '^5.0.0',\n },\n };\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nfunction codeTsconfig(): string {\n const tsconfig = {\n compilerOptions: {\n target: 'ES2020',\n module: 'CommonJS',\n moduleResolution: 'node',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: false,\n noEmit: true,\n },\n include: ['pack.ts'],\n };\n return `${JSON.stringify(tsconfig, null, 2)}\\n`;\n}\n\nfunction codeEntry(name: string, version: string): string {\n const code = slug(name).toUpperCase().replace(/-/g, '_');\n return [\n \"import { defineRule } from '@wairon/sdk';\",\n \"import type { RuleContext, Finding } from '@wairon/sdk';\",\n '',\n 'const exampleRule = defineRule({',\n ` name: '${slug(name)}-example',`,\n \" description: 'Example architectural rule. Replace with your own doctrine.',\",\n ` codes: ['${code}_EXAMPLE'],`,\n ' check(ctx: RuleContext): Finding[] {',\n ' const findings: Finding[] = [];',\n ' for (const component of ctx.components) {',\n ' // Inspect the spec tree and push findings as needed.',\n ' void component;',\n ' }',\n ' return findings;',\n ' },',\n '});',\n '',\n 'export default {',\n ` name: '${name}',`,\n ` version: '${version}',`,\n ' rules: [exampleRule],',\n '};',\n '',\n ].join('\\n');\n}\n\nfunction readme(name: string, kind: string, entry: string): string {\n return [\n `# ${name}`,\n '',\n `A wairon ${kind} pack.`,\n '',\n `- Envelope: \\`wairon-pack.yaml\\``,\n `- Entry: \\`${entry}\\``,\n '',\n 'Build an installable `.wpack` archive with `wairon pack build`.',\n '',\n ].join('\\n');\n}\n\nfunction skillStub(name: string): string {\n return [\n '---',\n `name: ${name}`,\n `description: ${name} authoring skill (stub).`,\n '---',\n '',\n `# ${name}`,\n '',\n 'Describe when this skill applies and what it guides.',\n '',\n ].join('\\n');\n}\n\nfunction slug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { zipSync, unzipSync, type Zippable } from 'fflate';\nimport type { ArchiveEntryMeta, PackFile } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Pack Archive Adapter (pack_archive_adapter_impl) — the ONLY zip-library + fs\n// I/O boundary of the SDK. Technology: fflate (pure-JS ZIP, no native deps).\n//\n// Acts only on already-validated inputs: it makes no path-safety or format\n// decisions (that is the codec's job). Enumeration reads sizes WITHOUT\n// inflating so the codec can enforce zip-bomb / size caps before any bytes are\n// decompressed.\n// ---------------------------------------------------------------------------\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', '.hg', '.svn']);\n\n/**\n * Enumerate every entry's metadata (path, compressed + uncompressed size, kind)\n * WITHOUT decompressing any bytes, so the codec can enforce caps before\n * inflation.\n */\nexport function listEntries(archive: Uint8Array): ArchiveEntryMeta[] {\n // Step 1: read the central directory via the zip library, mapping each record\n // to ArchiveEntryMeta without inflating any data. fflate's filter reports\n // {name, size (compressed), originalSize (uncompressed)} for every entry;\n // returning false skips decompression. Symlink detection reads the central\n // directory's external attributes (fflate's metadata omits the unix mode).\n const symlinks = detectSymlinkNames(archive);\n const metas: ArchiveEntryMeta[] = [];\n unzipSync(archive, {\n filter: (info): boolean => {\n metas.push({\n path: info.name,\n uncompressedSize: info.originalSize,\n compressedSize: info.size,\n kind: classifyKind(info.name, symlinks),\n });\n return false;\n },\n });\n // Step 2: return the entry metadata list.\n return metas;\n}\n\n/** Decompress and return the bytes of a single named entry. */\nexport function inflateEntry(archive: Uint8Array, entryPath: string): Uint8Array {\n // Step 1: locate the named entry and inflate only it.\n const inflated = unzipSync(archive, { filter: (info): boolean => info.name === entryPath });\n const bytes = inflated[entryPath];\n if (!bytes) throw new Error(`archive entry not found: ${entryPath}`);\n // Step 2: return the entry's decompressed bytes.\n return bytes;\n}\n\n/** Deflate a set of files (the envelope + pack contents) into a single ZIP buffer. */\nexport function assembleArchive(files: PackFile[]): Uint8Array {\n // Step 1: add each file to a zip container (deflating) and finalize.\n const zippable: Zippable = {};\n for (const file of files) zippable[file.path] = file.contents;\n const bytes = zipSync(zippable);\n // Step 2: return the archive bytes.\n return bytes;\n}\n\n/** Read a source pack directory recursively into a file map (POSIX paths + bytes). */\nexport function readPackDir(dir: string): PackFile[] {\n // Step 1: walk the directory recursively, reading each file into\n // { path: POSIX-relative, contents } (skipping node_modules and VCS dirs).\n const files: PackFile[] = [];\n walkPackDir(dir, dir, files);\n // Step 2: return the file map.\n return files;\n}\n\n/** Write a file map as a directory tree under destDir, creating parent directories. */\nexport function writeTree(destDir: string, files: PackFile[]): void {\n // Step 1: write each approved file.\n for (const file of files) {\n // Step 2 (writeEnd): create parent directories and write the file's bytes.\n const absolute = path.join(destDir, file.path);\n fs.mkdirSync(path.dirname(absolute), { recursive: true });\n fs.writeFileSync(absolute, file.contents);\n }\n // Step 3: done.\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction classifyKind(name: string, symlinks: Set<string>): string {\n if (symlinks.has(name)) return 'symlink';\n if (name.endsWith('/')) return 'dir';\n return 'file';\n}\n\nfunction walkPackDir(root: string, current: string, out: PackFile[]): void {\n for (const entry of fs.readdirSync(current, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue;\n walkPackDir(root, path.join(current, entry.name), out);\n } else if (entry.isFile()) {\n const absolute = path.join(current, entry.name);\n const relative = path.relative(root, absolute).split(path.sep).join('/');\n out.push({ path: relative, contents: fs.readFileSync(absolute) });\n }\n }\n}\n\n// Best-effort central-directory scan for symlink entries (unix S_IFLNK in the\n// external file attributes). fflate's high-level metadata omits the unix mode,\n// so the codec's symlink rejection needs this. Any parse trouble yields an\n// empty set — no worse than fflate alone, and confinement/size caps still apply.\nfunction detectSymlinkNames(archive: Uint8Array): Set<string> {\n const names = new Set<string>();\n try {\n const eocd = findEocd(archive);\n if (eocd < 0) return names;\n let p = readU32(archive, eocd + 16); // central directory offset\n const count = readU16(archive, eocd + 10);\n const decoder = new TextDecoder();\n for (let i = 0; i < count; i++) {\n if (readU32(archive, p) !== 0x02014b50) break; // central file header sig\n const versionMadeBy = readU16(archive, p + 4);\n const nameLen = readU16(archive, p + 28);\n const extraLen = readU16(archive, p + 30);\n const commentLen = readU16(archive, p + 32);\n const externalAttrs = readU32(archive, p + 38);\n const name = decoder.decode(archive.subarray(p + 46, p + 46 + nameLen));\n if ((versionMadeBy >> 8) === 3) { // unix host\n const unixMode = (externalAttrs >>> 16) & 0xffff;\n if ((unixMode & 0o170000) === 0o120000) names.add(name);\n }\n p += 46 + nameLen + extraLen + commentLen;\n }\n } catch {\n return names;\n }\n return names;\n}\n\nfunction findEocd(buf: Uint8Array): number {\n const minRecord = 22;\n const lowerBound = Math.max(0, buf.length - (minRecord + 0xffff));\n for (let i = buf.length - minRecord; i >= lowerBound; i--) {\n if (readU32(buf, i) === 0x06054b50) return i;\n }\n return -1;\n}\n\nfunction readU16(buf: Uint8Array, off: number): number {\n return buf[off] | (buf[off + 1] << 8);\n}\n\nfunction readU32(buf: Uint8Array, off: number): number {\n return (buf[off] | (buf[off + 1] << 8) | (buf[off + 2] << 16) | (buf[off + 3] << 24)) >>> 0;\n}\n","// ---------------------------------------------------------------------------\n// Rule-authoring contract (the code-pack compile target).\n//\n// Code packs are written against `@wairon/sdk`, never against wairon core. This\n// is a small, stable, hand-authored facade — deliberately NOT core's fat\n// RuleContext. `defineRule` returns the rule unchanged (identity + type\n// inference); the runtime shape `{ name, description?, codes: string[], check }`\n// is exactly what the core extension loader duck-types.\n// ---------------------------------------------------------------------------\n\n/** Severity of a finding a pack rule emits. */\nexport type RuleSeverity = 'error' | 'warning';\n\n/** A single issue a pack rule reports about the spec tree. */\nexport interface Finding {\n /** Pack-local issue code (surfaced namespaced by wairon, e.g. `<PACK>_<CODE>`). */\n code: string;\n /** 'error' | 'warning'. */\n severity: RuleSeverity;\n /** Human-readable explanation of the violation. */\n message: string;\n /** The spec id the finding is anchored to (optional). */\n specId?: string;\n}\n\n/**\n * A read-only spec node as seen by a pack rule: its id/name plus arbitrary\n * further fields (kept open so the facade stays stable as the spec model grows).\n */\nexport interface RuleSpecNode {\n id: string;\n name?: string;\n [key: string]: unknown;\n}\n\n/**\n * The minimal, stable view of the spec tree a code-pack rule inspects. A rule\n * reads these collections and returns findings — it never mutates state and\n * never reaches into wairon core internals.\n */\nexport interface RuleContext {\n /** The L0 system spec. */\n system: RuleSpecNode;\n /** All L1 subsystem specs. */\n subsystems: RuleSpecNode[];\n /** All L2 component specs. */\n components: RuleSpecNode[];\n /** All L3 interface specs. */\n interfaces: RuleSpecNode[];\n /** All L4 implementation specs. */\n implementations: RuleSpecNode[];\n /** All shared type/value-object specs. */\n types: RuleSpecNode[];\n}\n\n/**\n * A programmatic conformance rule shipped by a code pack. Its runtime shape —\n * `{ name, description?, codes: string[], check }` — is what wairon's extension\n * loader duck-types when it loads a `pack.cjs`.\n */\nexport interface SddRule {\n /** Stable rule id (kebab-case), e.g. \"my-portal-transport\". */\n name: string;\n /** One-line description of what the rule enforces and why. */\n description?: string;\n /** The issue codes this rule can emit. */\n codes: string[];\n /** Inspect the spec tree and return findings (empty when clean). */\n check(ctx: RuleContext): Finding[];\n}\n\n/**\n * Author an SddRule with full type inference. Returns the rule unchanged — it\n * exists purely so code packs get typed authoring without importing anything\n * from wairon core.\n */\nexport function defineRule(rule: SddRule): SddRule {\n return rule;\n}\n"],"mappings":"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","names":["exports","module","buildPack","buildTreeArchive","extractPack","extractTreeArchive","inspectArchive","inspectTreeArchive","scaffoldPack","path","import_js_yaml","yamlLoad","yamlDump","import_js_yaml","import_crypto","SUPPORTED_FORMAT_VERSION","yamlLoad","validateEnvelope","yamlDump","isSymlinkOrNonRegular","isStructurallyUnsafePath","rejectUnsafe","normalizeRelPath","escapesDestination","pathDepth","compressionRatio","sha256","canonicalDigestBytes","isBelow","parseSemverCore","relative","slug","yamlLoad","scaffoldPack","buildPack","inspectArchive","extractPack","buildTreeArchive","inspectTreeArchive","extractTreeArchive"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/index.ts","../src/orchestrator.ts","../src/codec.ts","../src/errors.ts","../src/treecodec.ts","../src/version.ts","../src/scaffold.ts","../src/archive.ts","../src/authoring.ts"],"sourcesContent":["{\n \"name\": \"@wairon/sdk\",\n \"version\": \"6.7.4-dev.10\",\n \"description\": \"Experimental: wairon pack-archive (.wpack) format authority and authoring toolkit — scaffold, build, inspect, and safely extract wairon extension packs.\",\n \"keywords\": [\n \"wairon\",\n \"sdd\",\n \"pack\",\n \"wpack\",\n \"archive\",\n \"developer-tools\",\n \"experimental\"\n ],\n \"author\": \"SYW\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/SYW-Apps/Waffle-AIron\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/SYW-Apps/Waffle-AIron.git\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"engines\": {\n \"node\": \"^22.23.4 || ^24.22.1 || >=26.12.1\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"clean\": \"rimraf dist\"\n },\n \"dependencies\": {\n \"fflate\": \"^0.8.2\",\n \"js-yaml\": \"^4.3.2\"\n },\n \"devDependencies\": {\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"^20.14.0\",\n \"rimraf\": \"^5.0.7\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.2\",\n \"vitest\": \"^4.1.9\"\n }\n}\n","import * as orchestrator from './orchestrator.js';\nimport * as codec from './codec.js';\nimport type {\n PackArchiveInfo,\n PackBuildResult,\n PackContents,\n PackExtractionLimits,\n PackExtractionResult,\n PackFile,\n PackScaffoldRequest,\n TreeArchiveInfo,\n TreeBuildResult,\n TreeExtractionResult,\n TreeRootSource,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// SDK Portal (sdk_portal_impl) — the @wairon/sdk package entry. Each capability\n// is a 1:1 forward to the SDK orchestrator with no logic of its own; the module\n// also re-exports the pure pack-authoring value objects and the rule-authoring\n// contract (compile-time types + the defineRule helper).\n// ---------------------------------------------------------------------------\n\n/** Scaffold a new pack project (declarative or code) into a directory; returns the created file paths. */\nexport function scaffoldPack(request: PackScaffoldRequest): string[] {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.scaffoldPack(request);\n}\n\n/** Build an installable .wpack archive from a pack directory. */\nexport function buildPack(sourceDir: string): PackBuildResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.buildPack(sourceDir);\n}\n\n/**\n * A pack's content integrity (`sha256-<hex>`) over its files as extracted —\n * the digest project.yaml pins and a registry publishes, one implementation\n * for every consumer.\n */\nexport function packContentDigest(files: readonly PackFile[]): string {\n // Step 1: forward to the pack codec.\n return codec.contentDigest(files);\n}\n\n/** Inspect + verify a .wpack archive without extracting it. */\nexport function inspectArchive(archive: Uint8Array, limits?: PackExtractionLimits): PackArchiveInfo {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.inspectArchive(archive, limits);\n}\n\n/** Read a .wpack archive in memory under the extraction guards; nothing is written. */\nexport function readPack(archive: Uint8Array, limits?: PackExtractionLimits): PackContents {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.readPack(archive, limits);\n}\n\n/** Safely extract a .wpack archive into a destination directory under enforced limits. */\nexport function extractPack(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n): PackExtractionResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.extractPack(archive, destDir, limits);\n}\n\n/** Pack a project's spec tree — the supplied roots' .wai directories — into a .waitree archive. */\nexport function buildTreeArchive(\n roots: TreeRootSource[],\n projectName: string,\n stateId?: string,\n includeDerived?: boolean,\n): TreeBuildResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.buildTreeArchive(roots, projectName, stateId, includeDerived);\n}\n\n/** Inspect a .waitree archive without extracting it. */\nexport function inspectTreeArchive(archive: Uint8Array): TreeArchiveInfo {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.inspectTreeArchive(archive);\n}\n\n/** Safely extract a .waitree archive into a destination project root under enforced limits. */\nexport function extractTreeArchive(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n refuseExecutableEntries?: boolean,\n): TreeExtractionResult {\n // Step 1: forward to the SDK orchestrator.\n return orchestrator.extractTreeArchive(archive, destDir, limits, refuseExecutableEntries);\n}\n\n// Re-export the pure pack-archive value objects...\nexport * from './types.js';\n// ...and the rule-authoring contract (SddRule + stable RuleContext/Finding facade + defineRule).\nexport * from './authoring.js';\n// ...and the one error every .wpack reader fails with, plus its code union.\nexport { PackArchiveError } from './errors.js';\nexport type { PackArchiveErrorCode } from './errors.js';\n","import * as path from 'path';\nimport { load as yamlLoad } from 'js-yaml';\nimport * as codec from './codec.js';\nimport * as treecodec from './treecodec.js';\nimport * as scaffold from './scaffold.js';\nimport * as packArchive from './archive.js';\nimport { SDK_VERSION } from './version.js';\nimport { PackArchiveError } from './errors.js';\nimport type {\n ArchiveEntryMeta,\n PackArchiveInfo,\n PackArchiveManifest,\n PackBuildResult,\n PackContents,\n PackExtractionLimits,\n PackExtractionResult,\n PackFile,\n PackScaffoldRequest,\n TreeArchiveInfo,\n TreeArchiveManifest,\n TreeBuildResult,\n TreeExtractionResult,\n TreeRootSource,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// SDK Orchestrator (sdk_orchestrator_impl) — the four pack workflows and the\n// three spec-tree archive workflows. Delegates format/safety decisions to the\n// codecs, template rendering to the pack scaffold, and all zip+fs I/O to\n// the archive adapter. Holds no state.\n//\n// Root DISCOVERY stays with the caller: the SDK never walks a spec tree, it\n// only archives the roots it is handed.\n// ---------------------------------------------------------------------------\n\nconst decode = (b: Uint8Array): string => new TextDecoder().decode(b);\nconst encode = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** Render the scaffold file map and write it under the target directory. */\nexport function scaffoldPack(request: PackScaffoldRequest): string[] {\n // Step 1: render the scaffold file map for the requested pack.\n const files = scaffold.render(request);\n // Step 2: write the rendered files as a directory tree under targetDir.\n packArchive.writeTree(request.targetDir, files);\n // Step 3: return the created file paths (targetDir-joined).\n return files.map((file) => path.join(request.targetDir, file.path));\n}\n\n/** Build an installable .wpack archive from a pack directory. */\nexport function buildPack(sourceDir: string): PackBuildResult {\n // Step 1: read the source pack directory into a file map.\n const files = packArchive.readPackDir(sourceDir);\n // Step 2: require an envelope.\n const envelope = files.find((file) => file.path === codec.ENVELOPE_FILENAME);\n if (!envelope) {\n // Step 3: reject a pack directory with no envelope.\n throw new Error('pack build requires a wairon-pack.yaml envelope (run `wairon pack init` to scaffold one)');\n }\n // Step 4 (parse): parse + validate the envelope (also version-gates the format).\n const manifest = codec.parseManifest(decode(envelope.contents));\n // Step 5: read the inner pack identity (pack.yaml, or package.json for code).\n const identity = readInnerIdentity(files, manifest);\n // Step 6: assert the envelope's name/version match the inner pack manifest.\n codec.verifyIdentity(manifest, identity.name, identity.version);\n // Step 7: seal integrity (entryDigests + digest + generatedBy) with no build time,\n // so the same content always builds the same archive and content digest.\n const sealed = codec.sealIntegrity(manifest, files, `@wairon/sdk@${SDK_VERSION}`);\n // Step 8: serialize the sealed manifest back to canonical envelope text.\n const sealedText = codec.serializeManifest(sealed);\n // Step 9: upsert wairon-pack.yaml (sealed envelope text) into the file map.\n const finalFiles = upsertEnvelope(files, sealedText);\n // Step 10: deflate the files + envelope into .wpack archive bytes.\n const archiveBytes = packArchive.assembleArchive(finalFiles);\n // Step 11: assemble PackArchiveInfo + suggestedFileName.\n const info = buildInfo(sealed, finalFiles);\n const suggestedFileName = `${sealed.name}-${sealed.version}.wpack`;\n // Step 12: return the build result.\n return { archive: archiveBytes, info, suggestedFileName };\n}\n\n/** The archive's entries; bytes that are not a readable ZIP carry no envelope, so they are NOT_A_PACK. */\nfunction listPackEntries(archive: Uint8Array): ArchiveEntryMeta[] {\n try {\n return packArchive.listEntries(archive);\n } catch (e) {\n throw new PackArchiveError('NOT_A_PACK', `not a .wpack archive (unreadable ZIP: ${e instanceof Error ? e.message : String(e)})`);\n }\n}\n\n/** Inspect + verify a .wpack archive without extracting it; every entry is vetted under the limits before anything is inflated. */\nexport function inspectArchive(archive: Uint8Array, limits?: PackExtractionLimits): PackArchiveInfo {\n // Step 1: did the caller omit limits?\n const effectiveLimits = limits === undefined\n // Step 2: fall back to the codec's default limit profile.\n ? codec.defaultLimits()\n : limits;\n // Step 3: enumerate archive entries without inflating.\n const entries = listPackEntries(archive);\n // Step 4: vet every entry under the effective limits, the envelope included.\n codec.planExtraction(entries, effectiveLimits);\n // Step 5: is there no wairon-pack.yaml entry?\n if (!entries.some((entry) => entry.path === codec.ENVELOPE_FILENAME)) {\n // Step 6: reject a non-.wpack archive.\n throw new PackArchiveError('NOT_A_PACK', 'not a .wpack archive (missing wairon-pack.yaml envelope)');\n }\n // Step 7 (readEnv): inflate just the envelope entry.\n const envelopeBytes = packArchive.inflateEntry(archive, codec.ENVELOPE_FILENAME);\n // Step 8: parse + version-check the envelope text.\n const manifest = codec.parseManifest(decode(envelopeBytes));\n // Step 9: compute compatibility against the running wairon version.\n const compatible = codec.checkCompatibility(manifest, SDK_VERSION);\n // Step 10: assemble PackArchiveInfo from the manifest + archive stats.\n const fileEntries = entries.filter((entry) => entry.kind === 'file');\n const totalUncompressedBytes = entries.reduce((sum, entry) => sum + entry.uncompressedSize, 0);\n const info: PackArchiveInfo = {\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n formatVersion: manifest.formatVersion,\n entryCount: fileEntries.length,\n totalUncompressedBytes,\n compatible,\n };\n if (manifest.minWaironVersion !== undefined) info.minWaironVersion = manifest.minWaironVersion;\n // Step 11: return the PackArchiveInfo (no extraction performed).\n return info;\n}\n\n/** Read a .wpack archive in memory under the limits: guards, envelope, integrity, inner manifest, identity. */\nexport function readPack(archive: Uint8Array, limits?: PackExtractionLimits): PackContents {\n // Step 1: did the caller omit limits?\n const effectiveLimits = limits === undefined\n // Step 2: fall back to the codec's default limit profile.\n ? codec.defaultLimits()\n : limits;\n // Step 3 (list): enumerate archive entries without inflating.\n const entries = listPackEntries(archive);\n // Step 4: compute the safe extraction plan under the effective limits.\n const plan = codec.planExtraction(entries, effectiveLimits);\n // Step 5: is there no wairon-pack.yaml among the approved paths?\n if (!plan.paths.includes(codec.ENVELOPE_FILENAME)) {\n // Step 6: reject a non-.wpack archive.\n throw new PackArchiveError('NOT_A_PACK', 'not a .wpack archive (missing wairon-pack.yaml envelope)');\n }\n // Step 7: initialize an empty file list.\n const files: PackFile[] = [];\n // Step 8: inflate each approved path from the plan.\n for (const approvedPath of plan.paths) {\n // Step 9: inflate one approved entry.\n const contents = packArchive.inflateEntry(archive, approvedPath);\n // Step 10 (inflateEnd): append { path, contents } to the file list.\n files.push({ path: approvedPath, contents });\n }\n // Step 11: parse the wairon-pack.yaml text into the envelope.\n const envelope = files.find((file) => file.path === codec.ENVELOPE_FILENAME) as PackFile;\n const manifest = codec.parseManifest(decode(envelope.contents));\n // Step 12: verify each inflated file against the envelope digests.\n codec.verifyIntegrity(manifest, files);\n // Step 13: read the inner pack manifest.\n const packManifest = codec.parseInnerManifest(manifest, files);\n // Step 14: verify the envelope's name and version against the inner manifest's.\n codec.verifyIdentity(manifest, String(packManifest.name), String(packManifest.version));\n // Step 15: return the envelope, the inner pack manifest and the files.\n return { manifest, packManifest, files };\n}\n\n/** Safely extract a .wpack archive into a destination directory under enforced limits. */\nexport function extractPack(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n): PackExtractionResult {\n // Step 1: read the archive in memory under the limits (fails before anything is written).\n const { manifest, files } = readPack(archive, limits);\n // Step 2: write the approved, integrity-checked files as a directory tree.\n const directory = path.resolve(destDir);\n packArchive.writeTree(directory, files);\n // Step 3: assemble PackExtractionResult.\n const result: PackExtractionResult = {\n directory,\n entryPath: manifest.entry,\n manifest,\n name: manifest.name,\n kind: manifest.kind,\n entryCount: files.length,\n };\n // Step 4: return where the pack landed + its parsed manifest.\n return result;\n}\n\n// ── Spec-tree archive workflows (.waitree) ──────────────────────────────────\n\n/** Pack a project's spec tree — the supplied roots' .wai directories — into a .waitree. */\nexport function buildTreeArchive(\n roots: TreeRootSource[],\n projectName: string,\n stateId?: string,\n includeDerived?: boolean,\n): TreeBuildResult {\n // Step 1: initialize an empty archive file map and an empty packed-roots list.\n const files: PackFile[] = [];\n const packedRoots: string[] = [];\n // Step 2: pack each supplied root.\n for (const root of roots) {\n // Step 3: read this root's .wai directory recursively into a file map.\n const rootFiles = packArchive.readPackDir(root.waiDir);\n // Step 4: keep only portable design state.\n const portable = treecodec.selectTreeFiles(rootFiles, includeDerived === true);\n // Step 5 (packEnd): prefix with this root's project-relative path + '.wai/'.\n const prefix = treeRootPrefix(root.relativePath);\n for (const file of portable) files.push({ path: `${prefix}${file.path}`, contents: file.contents });\n packedRoots.push(normalizeRootPath(root.relativePath));\n }\n // Step 6: did the roots yield no files at all?\n if (files.length === 0) {\n // Step 7: an export that silently carries nothing is worse than a failure.\n throw new Error('tree export found no spec-tree files under the supplied roots');\n }\n // Step 8: build the unsealed envelope.\n const manifest: TreeArchiveManifest = {\n formatVersion: 1,\n projectName,\n roots: packedRoots,\n waironVersion: SDK_VERSION,\n includesDerived: includeDerived === true,\n };\n if (stateId !== undefined) manifest.stateId = stateId;\n // Step 9: seal integrity (entryDigests + digest + generatedBy/generatedAt).\n const sealed = treecodec.sealTreeIntegrity(\n manifest,\n files,\n `@wairon/sdk@${SDK_VERSION}`,\n new Date().toISOString(),\n );\n // Step 10: serialize the sealed manifest to canonical envelope text.\n const sealedText = treecodec.serializeTreeManifest(sealed);\n // Step 11: upsert wairon-tree.yaml (sealed envelope text) into the file map.\n const finalFiles: PackFile[] = [\n ...files.filter((file) => file.path !== treecodec.TREE_ENVELOPE_FILENAME),\n { path: treecodec.TREE_ENVELOPE_FILENAME, contents: encode(sealedText) },\n ];\n // Step 12: deflate the files + envelope into .waitree archive bytes.\n const archiveBytes = packArchive.assembleArchive(finalFiles);\n // Step 13: derive the suggested file name from the project name.\n const suggestedFileName = `${slugify(projectName)}.waitree`;\n // Step 14: return the build result.\n return { archive: archiveBytes, manifest: sealed, suggestedFileName, fileCount: files.length };\n}\n\n/** Inspect a .waitree archive without extracting it. */\nexport function inspectTreeArchive(archive: Uint8Array): TreeArchiveInfo {\n // Step 1: enumerate archive entries without inflating.\n const entries = packArchive.listEntries(archive);\n // Step 2: is there no wairon-tree.yaml entry?\n if (!entries.some((entry) => entry.path === treecodec.TREE_ENVELOPE_FILENAME)) {\n // Step 3: reject a non-.waitree archive.\n throw new Error('not a .waitree archive (missing wairon-tree.yaml envelope)');\n }\n // Step 4 (readEnv): inflate just the envelope entry.\n const envelopeBytes = packArchive.inflateEntry(archive, treecodec.TREE_ENVELOPE_FILENAME);\n // Step 5: parse + version-check the envelope text.\n const manifest = treecodec.parseTreeManifest(decode(envelopeBytes));\n // Step 6: compute compatibility against the running wairon version.\n const compatible = treecodec.checkTreeCompatibility(manifest, SDK_VERSION);\n // Step 7: assemble TreeArchiveInfo from the manifest + archive stats.\n const fileEntries = entries.filter((entry) => entry.kind === 'file');\n const totalUncompressedBytes = entries.reduce((sum, entry) => sum + entry.uncompressedSize, 0);\n // Step 8: return the TreeArchiveInfo (no extraction performed).\n return { manifest, entryCount: fileEntries.length, totalUncompressedBytes, compatible };\n}\n\n/** Safely extract a .waitree archive into a destination project root under enforced limits. */\nexport function extractTreeArchive(\n archive: Uint8Array,\n destDir: string,\n limits?: PackExtractionLimits,\n refuseExecutableEntries?: boolean,\n): TreeExtractionResult {\n // Step 1: did the caller omit limits?\n const effectiveLimits = limits === undefined\n // Step 2: fall back to the codec's tree limit profile.\n ? treecodec.defaultTreeLimits()\n : limits;\n // Step 3 (list): enumerate archive entries without inflating (caps run pre-decompress).\n const entries = packArchive.listEntries(archive);\n // Step 4: compute the safe extraction plan (throws on any unsafe/oversized entry).\n const plan = treecodec.planTreeExtraction(entries, effectiveLimits);\n // Step 5: did the caller ask for the over-the-wire portability guard?\n if (refuseExecutableEntries === true) {\n // Step 6: refuse executable or non-spec-tree entries before anything is inflated.\n treecodec.assertPortableTreePaths(plan.paths);\n }\n // Step 7 (inflate): initialize an empty file list.\n const files: PackFile[] = [];\n // Step 8: inflate each approved path from the plan.\n for (const approvedPath of plan.paths) {\n // Step 9: inflate one approved entry.\n const contents = packArchive.inflateEntry(archive, approvedPath);\n // Step 10 (inflateEnd): append { path, contents } to the file list.\n files.push({ path: approvedPath, contents });\n }\n // Step 11: is the wairon-tree.yaml envelope missing from the inflated files?\n const envelope = files.find((file) => file.path === treecodec.TREE_ENVELOPE_FILENAME);\n if (!envelope) {\n // Step 12: reject a non-.waitree archive.\n throw new Error('not a .waitree archive (missing wairon-tree.yaml envelope)');\n }\n // Step 13 (parse): parse the envelope into the result manifest.\n const manifest = treecodec.parseTreeManifest(decode(envelope.contents));\n // Step 14: enforce integrity BEFORE writing (throws on mismatch; no-op when none carried).\n treecodec.verifyTreeIntegrity(manifest, files);\n // Step 15: write the approved, integrity-checked files as a directory tree.\n const directory = path.resolve(destDir);\n packArchive.writeTree(directory, files);\n // Step 16: assemble TreeExtractionResult.\n const result: TreeExtractionResult = {\n destDir: directory,\n manifest,\n roots: manifest.roots,\n writtenPaths: files.map((file) => file.path),\n };\n // Step 17: return where the tree landed + its parsed manifest.\n return result;\n}\n\n// --- helpers ---------------------------------------------------------------\n\n/** The archive-path prefix for one packed root: '.wai/' at the top, else '<dir>/.wai/'. */\nfunction treeRootPrefix(relativePath: string): string {\n const normalized = normalizeRootPath(relativePath);\n return normalized === '.' ? '.wai/' : `${normalized}/.wai/`;\n}\n\n/** A packed root's canonical project-relative form: POSIX separators, '.' for the top root. */\nfunction normalizeRootPath(relativePath: string): string {\n const posix = relativePath.split(path.sep).join('/').replace(/^\\.\\//, '').replace(/\\/+$/, '');\n return posix === '' || posix === '.' ? '.' : posix;\n}\n\n/** A file-name-safe stem for a project name. */\nfunction slugify(projectName: string): string {\n const slug = projectName\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'spec-tree';\n}\n\nfunction readInnerIdentity(files: PackFile[], manifest: PackArchiveManifest): { name: string; version: string } {\n const innerPath = manifest.kind === 'code' ? 'package.json' : manifest.entry;\n const inner = files.find((file) => file.path === innerPath);\n if (!inner) throw new Error(`pack build: inner pack manifest \"${innerPath}\" is missing`);\n const parsed = (manifest.kind === 'code'\n ? JSON.parse(decode(inner.contents))\n : yamlLoad(decode(inner.contents))) as Record<string, unknown> | null;\n const name = parsed?.name;\n const version = parsed?.version;\n if (typeof name !== 'string' || typeof version !== 'string') {\n throw new Error(`pack build: inner pack manifest \"${innerPath}\" lacks a name/version`);\n }\n return { name, version };\n}\n\nfunction upsertEnvelope(files: PackFile[], envelopeText: string): PackFile[] {\n const others = files.filter((file) => file.path !== codec.ENVELOPE_FILENAME);\n return [...others, { path: codec.ENVELOPE_FILENAME, contents: encode(envelopeText) }];\n}\n\nfunction buildInfo(manifest: PackArchiveManifest, files: PackFile[]): PackArchiveInfo {\n const totalUncompressedBytes = files.reduce((sum, file) => sum + file.contents.length, 0);\n const info: PackArchiveInfo = {\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n formatVersion: manifest.formatVersion,\n entryCount: files.length,\n totalUncompressedBytes,\n compatible: true,\n };\n if (manifest.minWaironVersion !== undefined) info.minWaironVersion = manifest.minWaironVersion;\n return info;\n}\n","import { load as yamlLoad, dump as yamlDump } from 'js-yaml';\nimport { createHash } from 'crypto';\nimport { PackArchiveError } from './errors.js';\nimport type {\n ArchiveEntryMeta,\n PackArchiveManifest,\n PackExtractionLimits,\n PackExtractionPlan,\n PackFile,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Pack Codec (pack_codec_impl) — PURE format + safety logic, no I/O.\n//\n// planExtraction is the single safety chokepoint (zip-slip / size / ratio /\n// depth / symlink guards, all pre-decompress). sealIntegrity/verifyIntegrity\n// are the produce/verify integrity pair. The codec stays pure: build time is\n// passed in, never read here.\n// ---------------------------------------------------------------------------\n\n/** Never part of a pack's content integrity: any path segment with one of these names. */\nconst DIGEST_EXCLUDED = new Set(['.install.yaml', '.git', 'node_modules', '.DS_Store']);\n\n/**\n * pack_codec.contentDigest — a pack's content integrity: sha256 folding each\n * file in sorted order as `<forward-slash path> NUL <bytes> NUL`, skipping\n * `.install.yaml`, `.git`, `node_modules` and `.DS_Store` wherever they sit,\n * written `sha256-<lowercase hex>`. The digest wairon's pack store computes\n * over an installed pack directory and project.yaml pins. Pure.\n */\nexport function contentDigest(files: readonly PackFile[]): string {\n // Steps 1-2: normalized paths, the skipped ones dropped, in sorted order.\n const kept = files\n .map((file) => ({ path: file.path.replace(/\\\\/g, '/').replace(/^\\/+/, ''), contents: file.contents }))\n .filter((file) => !file.path.split('/').some((segment) => DIGEST_EXCLUDED.has(segment)))\n .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));\n // Step 3: path NUL bytes NUL, folded in order.\n const hash = createHash('sha256');\n for (const file of kept) {\n hash.update(file.path);\n hash.update('\\0');\n hash.update(file.contents);\n hash.update('\\0');\n }\n // Step 4.\n return `sha256-${hash.digest('hex')}`;\n}\n\n/** The archive-root envelope filename. */\nexport const ENVELOPE_FILENAME = 'wairon-pack.yaml';\n\n/** The highest pack-archive format major this SDK understands. */\nconst SUPPORTED_FORMAT_VERSION = 1;\n\n/** The default extraction-safety profile: 4096 / 32 MiB / 8 MiB / 100:1 / depth 16. */\nconst DEFAULTS = {\n maxEntries: 4096,\n maxTotalUncompressedBytes: 32 * 1024 * 1024,\n maxEntryBytes: 8 * 1024 * 1024,\n maxCompressionRatio: 100,\n maxDepth: 16,\n} as const;\n\n/** Parse + validate the envelope text into a PackArchiveManifest; throws on malformed/newer-major. */\nexport function parseManifest(text: string): PackArchiveManifest {\n // Step 1: parse the envelope YAML text (ENVELOPE_INVALID on malformed YAML).\n let raw: unknown;\n try {\n raw = yamlLoad(text);\n } catch (err) {\n throw new PackArchiveError('ENVELOPE_INVALID', `malformed pack envelope (not valid YAML): ${(err as Error).message}`);\n }\n // Step 2: validate the required fields are present and well-typed.\n const manifest = validateEnvelope(raw);\n // Step 3: is the format major newer than this wairon supports?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: fail loudly rather than silently mis-read a newer format.\n throw new PackArchiveError(\n 'FORMAT_VERSION_UNSUPPORTED',\n `unsupported pack-archive formatVersion ${manifest.formatVersion} (newer than this wairon understands)`,\n );\n }\n // Step 5: return the parsed manifest.\n return manifest;\n}\n\n/** Serialize a manifest to canonical wairon-pack.yaml text (build path). */\nexport function serializeManifest(manifest: PackArchiveManifest): string {\n // Step 1: drop undefined optional fields for a clean, canonical envelope.\n const clean: Record<string, unknown> = {\n formatVersion: manifest.formatVersion,\n name: manifest.name,\n version: manifest.version,\n kind: manifest.kind,\n entry: manifest.entry,\n };\n if (manifest.minWaironVersion !== undefined) clean.minWaironVersion = manifest.minWaironVersion;\n if (manifest.digest !== undefined) clean.digest = manifest.digest;\n if (manifest.entryDigests !== undefined) clean.entryDigests = manifest.entryDigests;\n if (manifest.generatedBy !== undefined) clean.generatedBy = manifest.generatedBy;\n if (manifest.generatedAt !== undefined) clean.generatedAt = manifest.generatedAt;\n // Step 2: return the wairon-pack.yaml text.\n return yamlDump(clean, { sortKeys: false });\n}\n\n/** The default extraction-safety profile; callers override individual caps. */\nexport function defaultLimits(): PackExtractionLimits {\n // Step 1: return the default caps profile.\n return { ...DEFAULTS };\n}\n\n/** Compute the safe extraction plan from enumerated entries under `limits`, or throw. */\nexport function planExtraction(entries: ArchiveEntryMeta[], limits: PackExtractionLimits): PackExtractionPlan {\n // Step 1: resolve effective caps — each field of `limits` over the defaults.\n const caps = {\n maxEntries: limits.maxEntries ?? DEFAULTS.maxEntries,\n maxTotalUncompressedBytes: limits.maxTotalUncompressedBytes ?? DEFAULTS.maxTotalUncompressedBytes,\n maxEntryBytes: limits.maxEntryBytes ?? DEFAULTS.maxEntryBytes,\n maxCompressionRatio: limits.maxCompressionRatio ?? DEFAULTS.maxCompressionRatio,\n maxDepth: limits.maxDepth ?? DEFAULTS.maxDepth,\n };\n // Step 2: initialize an empty approved-path list and a running total of 0.\n const approved: string[] = [];\n let total = 0;\n // Step 3: vet each enumerated entry.\n for (const entry of entries) {\n // Step 4: reject symlinks/non-regular entries and structurally unsafe paths.\n if (isSymlinkOrNonRegular(entry.kind) || isStructurallyUnsafePath(entry.path)) {\n rejectUnsafe(entry.path);\n }\n // Directory entries are structural (writeTree recreates them from file\n // paths) — skip without approving, never inflate a 0-byte dir marker.\n if (entry.kind === 'dir') continue;\n // Step 5: normalize the entry path to a destination-relative POSIX path.\n const normalized = normalizeRelPath(entry.path);\n // Step 6: reject zip-slip and over-deep paths.\n if (escapesDestination(normalized)) {\n rejectUnsafe(entry.path);\n }\n if (pathDepth(normalized) > caps.maxDepth) {\n rejectLimit(`entry \"${entry.path}\" is nested deeper than maxDepth (${caps.maxDepth})`);\n }\n // Step 7: reject oversized entries and zip bombs.\n if (entry.uncompressedSize > caps.maxEntryBytes) {\n rejectLimit(`entry \"${entry.path}\" is larger than maxEntryBytes (${caps.maxEntryBytes})`);\n }\n if (compressionRatio(entry) > caps.maxCompressionRatio) {\n rejectLimit(`entry \"${entry.path}\" exceeds maxCompressionRatio (${caps.maxCompressionRatio}:1)`);\n }\n // Step 8 (vetEnd): accept — append the path and add its inflated size.\n approved.push(normalized);\n total += entry.uncompressedSize;\n }\n // Step 9: reject archives exceeding the aggregate caps.\n if (approved.length > caps.maxEntries) {\n rejectLimit(`archive holds more than maxEntries (${caps.maxEntries}) files`);\n }\n if (total > caps.maxTotalUncompressedBytes) {\n rejectLimit(`archive inflates beyond maxTotalUncompressedBytes (${caps.maxTotalUncompressedBytes})`);\n }\n // Step 11: return the approved plan.\n return { paths: approved, totalUncompressedBytes: total };\n}\n\n/** Assert the envelope's name/version match the inner pack manifest; throw on mismatch. */\nexport function verifyIdentity(manifest: PackArchiveManifest, packName: string, packVersion: string): void {\n // Step 1: do envelope name/version differ from the inner pack manifest?\n if (manifest.name !== packName || manifest.version !== packVersion) {\n // Step 2: reject a tampered/mis-assembled archive.\n throw new PackArchiveError(\n 'IDENTITY_MISMATCH',\n `envelope identity mismatch: envelope says ${manifest.name}@${manifest.version}, inner pack manifest says ${packName}@${packVersion}`,\n );\n }\n // Step 3: identity verified.\n}\n\n/** Verify every entry's sha256 against entryDigests; false when none carried, throws on mismatch. */\nexport function verifyIntegrity(manifest: PackArchiveManifest, files: PackFile[]): boolean {\n // Step 1: did the envelope carry no integrity data?\n if (!manifest.entryDigests) {\n // Step 2: no integrity data present — return false.\n return false;\n }\n const digests = manifest.entryDigests;\n // Step 3: does entryDigests name a file the archive does not hold, or does the\n // envelope's overall digest differ from the one recomputed over entryDigests?\n const held = new Set(files.map((file) => file.path));\n const missing = Object.keys(digests).find((path) => !held.has(path));\n if (missing !== undefined) {\n // Step 8 (mismatch): the envelope lists a file the archive does not hold.\n throw new PackArchiveError('DIGEST_MISMATCH', `integrity digest lists \"${missing}\", which the archive does not hold`);\n }\n if (manifest.digest !== undefined && manifest.digest !== sha256(canonicalDigestBytes(digests))) {\n // Step 8 (mismatch): the overall digest does not match the entry digests.\n throw new PackArchiveError('DIGEST_MISMATCH', 'integrity digest mismatch for the overall digest');\n }\n // Step 4: check each file's digest.\n for (const file of files) {\n // The envelope carries these digests and cannot digest itself — skip it.\n if (file.path === ENVELOPE_FILENAME) continue;\n // Step 5: does the recomputed sha256 differ from the recorded digest?\n if (sha256(file.contents) !== digests[file.path]) {\n // Step 8 (mismatch): a digest mismatch means tampering.\n throw new PackArchiveError('DIGEST_MISMATCH', `integrity digest mismatch for \"${file.path}\"`);\n }\n // Step 6 (checkEnd): this file's digest matches.\n }\n // Step 7: all digests matched — return true.\n return true;\n}\n\n/** Produce-side partner of verifyIntegrity: fill entryDigests + digest + stamps. */\nexport function sealIntegrity(\n manifest: PackArchiveManifest,\n files: PackFile[],\n generatedBy: string,\n generatedAt?: string,\n): PackArchiveManifest {\n // Step 1: initialize an empty entryDigests map.\n const entryDigests: Record<string, string> = {};\n // Step 2: hash each file.\n for (const file of files) {\n // The envelope is the carrier of these digests — never hash it into itself.\n if (file.path === ENVELOPE_FILENAME) continue;\n // Step 3 (hashEnd): compute sha256(file.contents) and record it under file.path.\n entryDigests[file.path] = sha256(file.contents);\n }\n // Step 4: compute an overall manifest digest over the sorted entryDigests.\n const digest = sha256(canonicalDigestBytes(entryDigests));\n // Step 5: set entryDigests, digest, generatedBy, and generatedAt when one is given.\n const sealed: PackArchiveManifest = { ...manifest, entryDigests, digest, generatedBy };\n if (generatedAt !== undefined) sealed.generatedAt = generatedAt;\n else delete sealed.generatedAt;\n // Step 6: return the sealed manifest.\n return sealed;\n}\n\n/** Whether the archive's formatVersion + minWaironVersion are compatible with `waironVersion`. */\nexport function checkCompatibility(manifest: PackArchiveManifest, waironVersion: string): boolean {\n // Step 1: is the archive format unsupported?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: incompatible.\n return false;\n }\n // Step 2: is the running wairon below the pack's minimum?\n if (manifest.minWaironVersion && isBelow(waironVersion, manifest.minWaironVersion)) {\n // Step 4: incompatible.\n return false;\n }\n // Step 3: compatible.\n return true;\n}\n\n/**\n * Read the inner pack manifest from the inflated files: package.json of a code\n * pack, the envelope's entry (pack.yaml) of a declarative pack. Throws\n * PACK_MANIFEST_INVALID when it is missing, unparseable or not a mapping.\n */\nexport function parseInnerManifest(manifest: PackArchiveManifest, files: readonly PackFile[]): Record<string, unknown> {\n // Step 1: pick the inner manifest's path.\n const innerPath = manifest.kind === 'code' ? 'package.json' : manifest.entry;\n // Step 2: is it missing among the files?\n const inner = files.find((file) => file.path === innerPath);\n if (!inner) {\n throw new PackArchiveError('PACK_MANIFEST_INVALID', `inner pack manifest \"${innerPath}\" is missing`);\n }\n // Step 3: parse it — JSON for package.json, YAML for pack.yaml.\n const text = new TextDecoder().decode(inner.contents);\n let parsed: unknown;\n try {\n parsed = manifest.kind === 'code' ? JSON.parse(text) : yamlLoad(text);\n } catch {\n parsed = undefined;\n }\n // Step 4-5: unparseable or not a mapping — refuse, naming the path.\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new PackArchiveError('PACK_MANIFEST_INVALID', `inner pack manifest \"${innerPath}\" is not a readable mapping`);\n }\n // Step 6: return the mapping as authored.\n return parsed as Record<string, unknown>;\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction rejectUnsafe(entryPath: string): never {\n throw new PackArchiveError('UNSAFE_PATH', `unsafe archive entry \"${entryPath}\" (symlink, non-file kind, or an unsafe or escaping path)`);\n}\n\nfunction rejectLimit(what: string): never {\n throw new PackArchiveError('LIMIT_EXCEEDED', `archive over a cap: ${what}`);\n}\n\nfunction invalidEnvelope(message: string): never {\n throw new PackArchiveError('ENVELOPE_INVALID', message);\n}\n\nfunction validateEnvelope(raw: unknown): PackArchiveManifest {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return invalidEnvelope('malformed pack envelope (not a YAML mapping)');\n }\n const o = raw as Record<string, unknown>;\n if (typeof o.formatVersion !== 'number') invalidEnvelope('pack envelope: formatVersion must be a number');\n if (typeof o.name !== 'string' || !o.name) invalidEnvelope('pack envelope: name is required');\n if (typeof o.version !== 'string' || !o.version) invalidEnvelope('pack envelope: version is required');\n if (typeof o.kind !== 'string' || (o.kind !== 'declarative' && o.kind !== 'code')) {\n invalidEnvelope('pack envelope: kind must be \"declarative\" or \"code\"');\n }\n if (typeof o.entry !== 'string' || !o.entry) invalidEnvelope('pack envelope: entry is required');\n // The integrity fields, when present, must be well-typed: an unquoted all-digit digest reads as\n // a YAML number, and skipping it would accept the archive unchecked.\n if (o.digest !== undefined && typeof o.digest !== 'string') {\n invalidEnvelope('pack envelope: digest must be a string (quote an all-digit digest)');\n }\n if (o.entryDigests !== undefined) {\n const digests = o.entryDigests;\n if (!digests || typeof digests !== 'object' || Array.isArray(digests)) {\n invalidEnvelope('pack envelope: entryDigests must be a mapping of path to digest');\n }\n for (const [entryPath, value] of Object.entries(digests as Record<string, unknown>)) {\n if (typeof value !== 'string') invalidEnvelope(`pack envelope: entryDigests[\"${entryPath}\"] must be a string (quote an all-digit digest)`);\n }\n }\n const manifest: PackArchiveManifest = {\n formatVersion: o.formatVersion,\n name: o.name,\n version: o.version,\n kind: o.kind,\n entry: o.entry,\n };\n if (typeof o.minWaironVersion === 'string') manifest.minWaironVersion = o.minWaironVersion;\n if (typeof o.digest === 'string') manifest.digest = o.digest;\n if (o.entryDigests && typeof o.entryDigests === 'object') {\n manifest.entryDigests = o.entryDigests as Record<string, string>;\n }\n if (typeof o.generatedBy === 'string') manifest.generatedBy = o.generatedBy;\n if (typeof o.generatedAt === 'string') manifest.generatedAt = o.generatedAt;\n return manifest;\n}\n\nfunction isSymlinkOrNonRegular(kind: string): boolean {\n return kind !== 'file' && kind !== 'dir';\n}\n\nfunction isStructurallyUnsafePath(p: string): boolean {\n if (p.includes('\\\\')) return true; // backslash\n if (/^[A-Za-z]:/.test(p)) return true; // drive letter\n if (p.startsWith('/')) return true; // absolute POSIX\n return p.split('/').some((seg) => seg === '..'); // parent traversal\n}\n\nfunction normalizeRelPath(p: string): string {\n return p\n .split('/')\n .filter((seg) => seg !== '' && seg !== '.')\n .join('/');\n}\n\nfunction escapesDestination(normalized: string): boolean {\n return normalized.startsWith('/') || normalized.split('/').some((seg) => seg === '..');\n}\n\nfunction pathDepth(normalized: string): number {\n return normalized.split('/').filter((seg) => seg !== '').length;\n}\n\nfunction compressionRatio(entry: ArchiveEntryMeta): number {\n if (entry.compressedSize > 0) return entry.uncompressedSize / entry.compressedSize;\n return entry.uncompressedSize > 0 ? Infinity : 0;\n}\n\nfunction canonicalDigestBytes(entryDigests: Record<string, string>): Uint8Array {\n const lines = Object.keys(entryDigests)\n .sort()\n .map((key) => `${key}:${entryDigests[key]}`)\n .join('\\n');\n return new TextEncoder().encode(lines);\n}\n\nfunction sha256(data: Uint8Array): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\nfunction isBelow(running: string, minimum: string): boolean {\n const [rMaj, rMin, rPat] = parseSemverCore(running);\n const [mMaj, mMin, mPat] = parseSemverCore(minimum);\n if (rMaj !== mMaj) return rMaj < mMaj;\n if (rMin !== mMin) return rMin < mMin;\n return rPat < mPat;\n}\n\nfunction parseSemverCore(v: string): [number, number, number] {\n const cleaned = v.trim().replace(/^[^0-9]*/, ''); // strip leading ^, ~, >=, v, etc.\n const core = cleaned.split(/[-+]/)[0]; // drop prerelease/build metadata\n const parts = core.split('.').map((n) => parseInt(n, 10));\n return [parts[0] || 0, parts[1] || 0, parts[2] || 0];\n}\n","// ---------------------------------------------------------------------------\n// Pack archive errors (pack_archive_error, pack_archive_error_code) — the one\n// error every .wpack reader of the SDK fails with. A caller matches on `code`,\n// never on message text.\n// ---------------------------------------------------------------------------\n\n/** Why a .wpack archive was refused. */\nexport type PackArchiveErrorCode =\n | 'NOT_A_PACK'\n | 'UNSAFE_PATH'\n | 'LIMIT_EXCEEDED'\n | 'ENVELOPE_INVALID'\n | 'FORMAT_VERSION_UNSUPPORTED'\n | 'PACK_MANIFEST_INVALID'\n | 'IDENTITY_MISMATCH'\n | 'DIGEST_MISMATCH';\n\n/** A .wpack archive was refused: a stable `code` beside a human message. */\nexport class PackArchiveError extends Error {\n readonly code: PackArchiveErrorCode;\n\n constructor(code: PackArchiveErrorCode, message: string) {\n super(message);\n this.name = 'PackArchiveError';\n this.code = code;\n Object.setPrototypeOf(this, PackArchiveError.prototype);\n }\n}\n","import { load as yamlLoad, dump as yamlDump } from 'js-yaml';\nimport { createHash } from 'crypto';\nimport type {\n ArchiveEntryMeta,\n PackExtractionLimits,\n PackExtractionPlan,\n PackFile,\n TreeArchiveManifest,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Tree Codec (tree_codec_impl) — PURE format + safety logic for the `.waitree`\n// spec-tree archive, no I/O and no clock.\n//\n// selectTreeFiles is the single portability decision (what belongs in a tree\n// archive at all); planTreeExtraction is the single pre-decompress safety\n// chokepoint; assertPortableTreePaths is the over-the-wire executable guard;\n// sealTreeIntegrity/verifyTreeIntegrity are the produce/verify pair.\n//\n// The small pure path/digest helpers below deliberately mirror the pack codec's\n// rather than importing them: tree_codec declares NO dependencies, and reaching\n// into pack_codec for them would make one codec depend on the other for a\n// handful of one-line functions.\n// ---------------------------------------------------------------------------\n\n/** The tree-archive envelope filename. */\nexport const TREE_ENVELOPE_FILENAME = 'wairon-tree.yaml';\n\n/** The highest tree-archive format major this SDK understands. */\nconst SUPPORTED_FORMAT_VERSION = 1;\n\n/**\n * The tree caps profile: looser than the pack profile on entry count and total\n * size (a real spec tree is thousands of small YAML files across several\n * chained roots) and stricter on nothing.\n */\nconst TREE_DEFAULTS = {\n maxEntries: 20000,\n maxTotalUncompressedBytes: 64 * 1024 * 1024,\n maxEntryBytes: 8 * 1024 * 1024,\n maxCompressionRatio: 100,\n maxDepth: 24,\n} as const;\n\n/** Root-relative directories holding REGENERABLE artifacts — never portable design state. */\nconst DERIVED_ROOTS = ['generated', 'docs'];\n\n/** Executable extensions: a bundled code pack's entry can ride inside a tree. */\nconst EXECUTABLE_EXT_RE = /\\.(c|m)?js$/i;\n\n/** The directory every packed root's content lives under, inside the archive. */\nconst WAI_SEGMENT = '.wai';\n\n/** Parse + validate the envelope text into a TreeArchiveManifest; throws on malformed/newer-major. */\nexport function parseTreeManifest(text: string): TreeArchiveManifest {\n // Step 1: parse the envelope YAML text (throws on malformed YAML).\n const raw = yamlLoad(text);\n // Step 2: validate the required fields are present and well-typed.\n const manifest = validateEnvelope(raw);\n // Step 3: is the format major newer than this wairon supports?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: fail loudly rather than silently mis-read a newer format.\n throw new Error('unsupported tree-archive formatVersion (newer than this wairon understands)');\n }\n // Step 5: return the parsed manifest.\n return manifest;\n}\n\n/** Serialize a manifest to canonical wairon-tree.yaml text (export path). */\nexport function serializeTreeManifest(manifest: TreeArchiveManifest): string {\n // Step 1: drop undefined optional fields for a clean, canonical envelope.\n const clean: Record<string, unknown> = {\n formatVersion: manifest.formatVersion,\n projectName: manifest.projectName,\n roots: manifest.roots,\n };\n if (manifest.stateId !== undefined) clean.stateId = manifest.stateId;\n if (manifest.waironVersion !== undefined) clean.waironVersion = manifest.waironVersion;\n if (manifest.minWaironVersion !== undefined) clean.minWaironVersion = manifest.minWaironVersion;\n if (manifest.includesDerived !== undefined) clean.includesDerived = manifest.includesDerived;\n if (manifest.digest !== undefined) clean.digest = manifest.digest;\n if (manifest.entryDigests !== undefined) clean.entryDigests = manifest.entryDigests;\n if (manifest.generatedBy !== undefined) clean.generatedBy = manifest.generatedBy;\n if (manifest.generatedAt !== undefined) clean.generatedAt = manifest.generatedAt;\n // Step 2: return the wairon-tree.yaml text.\n return yamlDump(clean, { sortKeys: false });\n}\n\n/** The tree extraction-safety profile; callers override individual caps. */\nexport function defaultTreeLimits(): PackExtractionLimits {\n // Step 1: return the tree caps profile.\n return { ...TREE_DEFAULTS };\n}\n\n/**\n * Decide which of a root's files are portable design state: keep authored spec\n * state, drop regenerable artifacts unless the caller asked for them. Paths are\n * relative to the root's `.wai/` directory.\n */\nexport function selectTreeFiles(files: PackFile[], includeDerived: boolean): PackFile[] {\n // Step 1: did the caller ask for regenerable artifacts too?\n if (includeDerived) {\n // Step 2: return the file map unchanged — an explicit full-fidelity archive.\n return files;\n }\n // Step 3: drop every file under a regenerable root — a moved tree carries the\n // design, not its rendered output, which the destination regenerates.\n const kept = files.filter((file) => !isDerivedPath(file.path));\n // Step 4: return the portable design state.\n return kept;\n}\n\n/** Compute the safe extraction plan from enumerated entries under `limits`, or throw. */\nexport function planTreeExtraction(entries: ArchiveEntryMeta[], limits: PackExtractionLimits): PackExtractionPlan {\n // Step 1: resolve effective caps — each field of `limits` over the tree defaults.\n const caps = {\n maxEntries: limits.maxEntries ?? TREE_DEFAULTS.maxEntries,\n maxTotalUncompressedBytes: limits.maxTotalUncompressedBytes ?? TREE_DEFAULTS.maxTotalUncompressedBytes,\n maxEntryBytes: limits.maxEntryBytes ?? TREE_DEFAULTS.maxEntryBytes,\n maxCompressionRatio: limits.maxCompressionRatio ?? TREE_DEFAULTS.maxCompressionRatio,\n maxDepth: limits.maxDepth ?? TREE_DEFAULTS.maxDepth,\n };\n // Step 2: initialize an empty approved-path list and a running total of 0.\n const approved: string[] = [];\n let total = 0;\n // Step 3: vet each enumerated entry.\n for (const entry of entries) {\n // Step 4: reject symlinks/non-regular entries and structurally unsafe paths.\n if (isSymlinkOrNonRegular(entry.kind) || isStructurallyUnsafePath(entry.path)) {\n rejectUnsafe();\n }\n // Directory entries are structural (writeTree recreates them from file\n // paths) — skip without approving, never inflate a 0-byte dir marker.\n if (entry.kind === 'dir') continue;\n // Step 5: normalize the entry path to a destination-relative POSIX path.\n const normalized = normalizeRelPath(entry.path);\n // Step 6: reject zip-slip and over-deep paths.\n if (escapesDestination(normalized) || pathDepth(normalized) > caps.maxDepth) {\n rejectUnsafe();\n }\n // Step 7: reject oversized entries and zip bombs.\n if (entry.uncompressedSize > caps.maxEntryBytes || compressionRatio(entry) > caps.maxCompressionRatio) {\n rejectUnsafe();\n }\n // Step 8 (vetEnd): accept — append the path and add its inflated size.\n approved.push(normalized);\n total += entry.uncompressedSize;\n }\n // Step 9: reject archives exceeding the aggregate caps.\n if (approved.length > caps.maxEntries || total > caps.maxTotalUncompressedBytes) {\n rejectUnsafe();\n }\n // Step 11: return the approved plan.\n return { paths: approved, totalUncompressedBytes: total };\n}\n\n/**\n * Assert the planned paths carry no executable content and nothing outside a\n * spec-tree root. Called by any surface accepting an archive over the wire; a\n * local extraction on the developer's own machine may skip it.\n */\nexport function assertPortableTreePaths(paths: string[]): void {\n // Step 1: check each planned path.\n for (const entryPath of paths) {\n // Step 2: is this an executable file (a bundled code pack's entry)?\n if (EXECUTABLE_EXT_RE.test(entryPath)) {\n // Step 6 (rejectExecutable): same guidance the pack surface gives.\n throw new Error(\n 'refused: the archive carries executable content. Only declarative spec state transfers over this ' +\n 'surface; rule/code packs are executable and install via the trusted filesystem (mount into ' +\n 'WAIRON_PACKS_DIR, or run `wairon packs add`).',\n );\n }\n // Step 3: does the path sit outside any recognized spec-tree root?\n if (entryPath !== TREE_ENVELOPE_FILENAME && !isUnderWaiRoot(entryPath)) {\n // Step 7 (rejectForeign): a tree archive carries .wai trees, never arbitrary project files.\n throw new Error(`refused: the archive carries an entry outside any spec-tree root (\"${entryPath}\")`);\n }\n // Step 4 (checkEnd): this path is portable spec-tree content.\n }\n // Step 5: every path is portable.\n}\n\n/** Verify every entry's sha256 against entryDigests; false when none carried, throws on mismatch. */\nexport function verifyTreeIntegrity(manifest: TreeArchiveManifest, files: PackFile[]): boolean {\n // Step 1: did the envelope carry no integrity data?\n if (!manifest.entryDigests) {\n // Step 2: no integrity data present — return false.\n return false;\n }\n const digests = manifest.entryDigests;\n // Step 3: check each file's digest.\n for (const file of files) {\n // The envelope carries these digests and cannot digest itself — skip it.\n if (file.path === TREE_ENVELOPE_FILENAME) continue;\n // Step 4: does the recomputed sha256 differ from the recorded digest?\n if (sha256(file.contents) !== digests[file.path]) {\n // Step 7: a digest mismatch means tampering.\n throw new Error('tree integrity digest mismatch');\n }\n // Step 5 (checkEnd): this file's digest matches.\n }\n // Step 6: all digests matched — return true.\n return true;\n}\n\n/** Produce-side partner of verifyTreeIntegrity: fill entryDigests + digest + stamps. */\nexport function sealTreeIntegrity(\n manifest: TreeArchiveManifest,\n files: PackFile[],\n generatedBy: string,\n generatedAt: string,\n): TreeArchiveManifest {\n // Step 1: initialize an empty entryDigests map.\n const entryDigests: Record<string, string> = {};\n // Step 2: hash each file.\n for (const file of files) {\n // The envelope is the carrier of these digests — never hash it into itself.\n if (file.path === TREE_ENVELOPE_FILENAME) continue;\n // Step 3 (hashEnd): compute sha256(file.contents) and record it under file.path.\n entryDigests[file.path] = sha256(file.contents);\n }\n // Step 4: compute an overall manifest digest over the sorted entryDigests.\n const digest = sha256(canonicalDigestBytes(entryDigests));\n // Step 5: set entryDigests, digest, generatedBy, generatedAt.\n // Step 6: return the sealed manifest.\n return { ...manifest, entryDigests, digest, generatedBy, generatedAt };\n}\n\n/** Whether the archive's formatVersion + minWaironVersion are compatible with `waironVersion`. */\nexport function checkTreeCompatibility(manifest: TreeArchiveManifest, waironVersion: string): boolean {\n // Step 1: is the archive format unsupported?\n if (Math.trunc(manifest.formatVersion) > SUPPORTED_FORMAT_VERSION) {\n // Step 4: incompatible.\n return false;\n }\n // Step 2: is the running wairon below the archive's minimum?\n if (manifest.minWaironVersion && isBelow(waironVersion, manifest.minWaironVersion)) {\n // Step 4: incompatible.\n return false;\n }\n // Step 3: compatible.\n return true;\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction rejectUnsafe(): never {\n throw new Error('reject: unsafe or oversized tree-archive entry (zip-slip / size / ratio / depth guard)');\n}\n\nfunction validateEnvelope(raw: unknown): TreeArchiveManifest {\n if (!raw || typeof raw !== 'object') {\n throw new Error('malformed tree envelope (not a YAML mapping)');\n }\n const o = raw as Record<string, unknown>;\n if (typeof o.formatVersion !== 'number') throw new Error('tree envelope: formatVersion must be a number');\n if (typeof o.projectName !== 'string' || !o.projectName) throw new Error('tree envelope: projectName is required');\n if (!Array.isArray(o.roots) || o.roots.length === 0 || o.roots.some((r) => typeof r !== 'string' || !r)) {\n throw new Error('tree envelope: roots must be a non-empty list of project-relative directories');\n }\n const manifest: TreeArchiveManifest = {\n formatVersion: o.formatVersion,\n projectName: o.projectName,\n roots: o.roots as string[],\n };\n if (typeof o.stateId === 'string') manifest.stateId = o.stateId;\n if (typeof o.waironVersion === 'string') manifest.waironVersion = o.waironVersion;\n if (typeof o.minWaironVersion === 'string') manifest.minWaironVersion = o.minWaironVersion;\n if (typeof o.includesDerived === 'boolean') manifest.includesDerived = o.includesDerived;\n if (typeof o.digest === 'string') manifest.digest = o.digest;\n if (o.entryDigests && typeof o.entryDigests === 'object') {\n manifest.entryDigests = o.entryDigests as Record<string, string>;\n }\n if (typeof o.generatedBy === 'string') manifest.generatedBy = o.generatedBy;\n if (typeof o.generatedAt === 'string') manifest.generatedAt = o.generatedAt;\n return manifest;\n}\n\n/** True for a path under a regenerable root, relative to a root's .wai/ directory. */\nfunction isDerivedPath(relPath: string): boolean {\n const first = relPath.split('/')[0];\n return DERIVED_ROOTS.includes(first);\n}\n\n/** True when an archive path lives under some root's .wai/ directory. */\nfunction isUnderWaiRoot(archivePath: string): boolean {\n const segments = archivePath.split('/');\n // The .wai segment must exist AND carry content beneath it — a bare '.wai'\n // entry names a directory, not spec-tree state.\n const at = segments.indexOf(WAI_SEGMENT);\n return at >= 0 && at < segments.length - 1;\n}\n\nfunction isSymlinkOrNonRegular(kind: string): boolean {\n return kind !== 'file' && kind !== 'dir';\n}\n\nfunction isStructurallyUnsafePath(p: string): boolean {\n if (p.includes('\\\\')) return true; // backslash\n if (/^[A-Za-z]:/.test(p)) return true; // drive letter\n if (p.startsWith('/')) return true; // absolute POSIX\n return p.split('/').some((seg) => seg === '..'); // parent traversal\n}\n\nfunction normalizeRelPath(p: string): string {\n return p\n .split('/')\n .filter((seg) => seg !== '' && seg !== '.')\n .join('/');\n}\n\nfunction escapesDestination(normalized: string): boolean {\n return normalized.startsWith('/') || normalized.split('/').some((seg) => seg === '..');\n}\n\nfunction pathDepth(normalized: string): number {\n return normalized.split('/').filter((seg) => seg !== '').length;\n}\n\nfunction compressionRatio(entry: ArchiveEntryMeta): number {\n if (entry.compressedSize > 0) return entry.uncompressedSize / entry.compressedSize;\n return entry.uncompressedSize > 0 ? Infinity : 0;\n}\n\nfunction canonicalDigestBytes(entryDigests: Record<string, string>): Uint8Array {\n const lines = Object.keys(entryDigests)\n .sort()\n .map((key) => `${key}:${entryDigests[key]}`)\n .join('\\n');\n return new TextEncoder().encode(lines);\n}\n\nfunction sha256(data: Uint8Array): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\nfunction isBelow(running: string, minimum: string): boolean {\n const [rMaj, rMin, rPat] = parseSemverCore(running);\n const [mMaj, mMin, mPat] = parseSemverCore(minimum);\n if (rMaj !== mMaj) return rMaj < mMaj;\n if (rMin !== mMin) return rMin < mMin;\n return rPat < mPat;\n}\n\nfunction parseSemverCore(v: string): [number, number, number] {\n const cleaned = v.trim().replace(/^[^0-9]*/, ''); // strip leading ^, ~, >=, v, etc.\n const core = cleaned.split(/[-+]/)[0]; // drop prerelease/build metadata\n const parts = core.split('.').map((n) => parseInt(n, 10));\n return [parts[0] || 0, parts[1] || 0, parts[2] || 0];\n}\n","// The running @wairon/sdk version — stamped into built archives (generatedBy)\n// and used as the \"running wairon version\" for pack version-compatibility\n// checks. tsup inlines package.json at build time; at runtime the require\n// resolves against the shipped package (../package.json from dist/).\n\nexport const SDK_VERSION: string = loadVersion();\n\nfunction loadVersion(): string {\n try {\n const pkg = require('../package.json') as { version?: string };\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n","import type { PackFile, PackScaffoldRequest } from './types.js';\nimport { SDK_VERSION } from './version.js';\n\n// ---------------------------------------------------------------------------\n// Pack Scaffold (pack_scaffold_impl) — PURE template rendering for\n// `wairon pack init`. Produces an in-memory file map; writes nothing. Code\n// packs pin @wairon/sdk to the running SDK version.\n// ---------------------------------------------------------------------------\n\nconst enc = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** Render the scaffold file map for the requested pack (declarative or code). */\nexport function render(request: PackScaffoldRequest): PackFile[] {\n const version = request.version ?? '0.1.0';\n let files: PackFile[];\n // Step 1: which variant?\n if (request.kind === 'code') {\n // Step 2: render the code-pack file map.\n files = renderCodePack(request.name, version);\n // Step 3: skip the declarative variant (fall through to the skill gate).\n } else {\n // Step 4 (declVariant): render the declarative-pack file map.\n files = renderDeclarativePack(request.name, version);\n }\n // Step 5 (skillGate): include a skill stub?\n if (request.withSkill) {\n // Step 6: append a skills/<id>/SKILL.md stub to the file map.\n files.push(renderSkillStub(request.name, version));\n }\n // Step 7 (done): return the rendered file map.\n return files;\n}\n\n// --- variant renderers -----------------------------------------------------\n\nfunction renderDeclarativePack(name: string, version: string): PackFile[] {\n return [\n { path: 'wairon-pack.yaml', contents: enc(declarativeEnvelope(name, version)) },\n { path: 'pack.yaml', contents: enc(declarativeManifest(name, version)) },\n { path: 'README.md', contents: enc(readme(name, 'declarative', 'pack.yaml')) },\n ];\n}\n\nfunction renderCodePack(name: string, version: string): PackFile[] {\n return [\n { path: 'wairon-pack.yaml', contents: enc(codeEnvelope(name, version)) },\n { path: 'package.json', contents: enc(codePackageJson(name, version)) },\n { path: 'tsconfig.json', contents: enc(codeTsconfig()) },\n { path: 'pack.ts', contents: enc(codeEntry(name, version)) },\n { path: 'README.md', contents: enc(readme(name, 'code', 'pack.cjs')) },\n ];\n}\n\nfunction renderSkillStub(name: string, _version: string): PackFile {\n const id = slug(name);\n return { path: `skills/${id}/SKILL.md`, contents: enc(skillStub(name)) };\n}\n\n// --- templates -------------------------------------------------------------\n\nfunction declarativeEnvelope(name: string, version: string): string {\n return [\n 'formatVersion: 1',\n `name: ${name}`,\n `version: ${version}`,\n 'kind: declarative',\n 'entry: pack.yaml',\n '',\n ].join('\\n');\n}\n\n/** A version's release core (major.minor.patch): a pre-release never becomes a minimum. */\nfunction releaseCore(version: string): string {\n return version.split(/[-+]/)[0];\n}\n\nfunction codeEnvelope(name: string, version: string): string {\n return [\n 'formatVersion: 1',\n `name: ${name}`,\n `version: ${version}`,\n 'kind: code',\n 'entry: pack.cjs',\n `minWaironVersion: ${releaseCore(SDK_VERSION)}`,\n '',\n ].join('\\n');\n}\n\nfunction declarativeManifest(name: string, version: string): string {\n return [\n `name: ${name}`,\n `version: ${version}`,\n '',\n '# Custom architectural profiles this pack contributes (example, commented):',\n '# profiles:',\n '# my-profile:',\n '# family: backend-like',\n '# forbiddenStereotypes:',\n '# - types: [Adapter]',\n '# reason: \"Domain components must not touch adapters directly.\"',\n 'profiles: {}',\n '',\n '# Target language / platform tables (example, commented):',\n '# languages:',\n '# rust:',\n '# unsupportedFlow: {}',\n 'languages: {}',\n '',\n '# Reusable, versioned architecture patterns:',\n 'patterns: []',\n '',\n ].join('\\n');\n}\n\nfunction codePackageJson(name: string, version: string): string {\n const pkg = {\n name,\n version,\n private: true,\n scripts: {\n build: 'esbuild pack.ts --bundle --platform=node --packages=external --format=cjs --outfile=pack.cjs',\n },\n dependencies: {\n '@wairon/sdk': SDK_VERSION,\n },\n devDependencies: {\n esbuild: '^0.21.0',\n typescript: '^5.0.0',\n },\n };\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nfunction codeTsconfig(): string {\n const tsconfig = {\n compilerOptions: {\n target: 'ES2020',\n module: 'CommonJS',\n moduleResolution: 'node',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: false,\n noEmit: true,\n },\n include: ['pack.ts'],\n };\n return `${JSON.stringify(tsconfig, null, 2)}\\n`;\n}\n\nfunction codeEntry(name: string, version: string): string {\n const code = slug(name).toUpperCase().replace(/-/g, '_');\n return [\n \"import { defineRule } from '@wairon/sdk';\",\n \"import type { RuleContext, Finding } from '@wairon/sdk';\",\n '',\n 'const exampleRule = defineRule({',\n ` name: '${slug(name)}-example',`,\n \" description: 'Example architectural rule. Replace with your own doctrine.',\",\n ` codes: ['${code}_EXAMPLE'],`,\n ' check(ctx: RuleContext): Finding[] {',\n ' const findings: Finding[] = [];',\n ' for (const component of ctx.components) {',\n ' // Inspect the spec tree and push findings as needed.',\n ' void component;',\n ' }',\n ' return findings;',\n ' },',\n '});',\n '',\n 'export default {',\n ` name: '${name}',`,\n ` version: '${version}',`,\n ' rules: [exampleRule],',\n '};',\n '',\n ].join('\\n');\n}\n\nfunction readme(name: string, kind: string, entry: string): string {\n return [\n `# ${name}`,\n '',\n `A wairon ${kind} pack.`,\n '',\n `- Envelope: \\`wairon-pack.yaml\\``,\n `- Entry: \\`${entry}\\``,\n '',\n 'Build an installable `.wpack` archive with `wairon pack build`.',\n '',\n ].join('\\n');\n}\n\nfunction skillStub(name: string): string {\n return [\n '---',\n `name: ${name}`,\n `description: ${name} authoring skill (stub).`,\n '---',\n '',\n `# ${name}`,\n '',\n 'Describe when this skill applies and what it guides.',\n '',\n ].join('\\n');\n}\n\nfunction slug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { zipSync, unzipSync, type Zippable } from 'fflate';\nimport type { ArchiveEntryMeta, PackFile } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Pack Archive Adapter (pack_archive_adapter_impl) — the ONLY zip-library + fs\n// I/O boundary of the SDK. Technology: fflate (pure-JS ZIP, no native deps).\n//\n// Acts only on already-validated inputs: it makes no path-safety or format\n// decisions (that is the codec's job). Enumeration reads sizes WITHOUT\n// inflating so the codec can enforce zip-bomb / size caps before any bytes are\n// decompressed.\n// ---------------------------------------------------------------------------\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', '.hg', '.svn']);\n\n/**\n * Enumerate every entry's metadata (path, compressed + uncompressed size, kind)\n * WITHOUT decompressing any bytes, so the codec can enforce caps before\n * inflation.\n */\nexport function listEntries(archive: Uint8Array): ArchiveEntryMeta[] {\n // Step 1: read the central directory via the zip library, mapping each record\n // to ArchiveEntryMeta without inflating any data. fflate's filter reports\n // {name, size (compressed), originalSize (uncompressed)} for every entry;\n // returning false skips decompression. Symlink detection reads the central\n // directory's external attributes (fflate's metadata omits the unix mode).\n const symlinks = detectSymlinkNames(archive);\n const metas: ArchiveEntryMeta[] = [];\n unzipSync(archive, {\n filter: (info): boolean => {\n metas.push({\n path: info.name,\n uncompressedSize: info.originalSize,\n compressedSize: info.size,\n kind: classifyKind(info.name, symlinks),\n });\n return false;\n },\n });\n // Step 2: return the entry metadata list.\n return metas;\n}\n\n/** Decompress and return the bytes of a single named entry. */\nexport function inflateEntry(archive: Uint8Array, entryPath: string): Uint8Array {\n // Step 1: locate the named entry and inflate only it.\n const inflated = unzipSync(archive, { filter: (info): boolean => info.name === entryPath });\n const bytes = inflated[entryPath];\n if (!bytes) throw new Error(`archive entry not found: ${entryPath}`);\n // Step 2: return the entry's decompressed bytes.\n return bytes;\n}\n\n/** Deflate a set of files (the envelope + pack contents) into a single ZIP buffer. */\nexport function assembleArchive(files: PackFile[]): Uint8Array {\n // Step 1: add each file to a zip container (deflating) and finalize.\n const zippable: Zippable = {};\n for (const file of files) zippable[file.path] = file.contents;\n const bytes = zipSync(zippable);\n // Step 2: return the archive bytes.\n return bytes;\n}\n\n/** Read a source pack directory recursively into a file map (POSIX paths + bytes). */\nexport function readPackDir(dir: string): PackFile[] {\n // Step 1: walk the directory recursively, reading each file into\n // { path: POSIX-relative, contents } (skipping node_modules and VCS dirs).\n const files: PackFile[] = [];\n walkPackDir(dir, dir, files);\n // Step 2: return the file map.\n return files;\n}\n\n/** Write a file map as a directory tree under destDir, creating parent directories. */\nexport function writeTree(destDir: string, files: PackFile[]): void {\n // Step 1: write each approved file.\n for (const file of files) {\n // Step 2 (writeEnd): create parent directories and write the file's bytes.\n const absolute = path.join(destDir, file.path);\n fs.mkdirSync(path.dirname(absolute), { recursive: true });\n fs.writeFileSync(absolute, file.contents);\n }\n // Step 3: done.\n}\n\n// --- helpers ---------------------------------------------------------------\n\nfunction classifyKind(name: string, symlinks: Set<string>): string {\n if (symlinks.has(name)) return 'symlink';\n if (name.endsWith('/')) return 'dir';\n return 'file';\n}\n\nfunction walkPackDir(root: string, current: string, out: PackFile[]): void {\n for (const entry of fs.readdirSync(current, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue;\n walkPackDir(root, path.join(current, entry.name), out);\n } else if (entry.isFile()) {\n const absolute = path.join(current, entry.name);\n const relative = path.relative(root, absolute).split(path.sep).join('/');\n out.push({ path: relative, contents: fs.readFileSync(absolute) });\n }\n }\n}\n\n// Best-effort central-directory scan for symlink entries (unix S_IFLNK in the\n// external file attributes). fflate's high-level metadata omits the unix mode,\n// so the codec's symlink rejection needs this. Any parse trouble yields an\n// empty set — no worse than fflate alone, and confinement/size caps still apply.\nfunction detectSymlinkNames(archive: Uint8Array): Set<string> {\n const names = new Set<string>();\n try {\n const eocd = findEocd(archive);\n if (eocd < 0) return names;\n let p = readU32(archive, eocd + 16); // central directory offset\n const count = readU16(archive, eocd + 10);\n const decoder = new TextDecoder();\n for (let i = 0; i < count; i++) {\n if (readU32(archive, p) !== 0x02014b50) break; // central file header sig\n const versionMadeBy = readU16(archive, p + 4);\n const nameLen = readU16(archive, p + 28);\n const extraLen = readU16(archive, p + 30);\n const commentLen = readU16(archive, p + 32);\n const externalAttrs = readU32(archive, p + 38);\n const name = decoder.decode(archive.subarray(p + 46, p + 46 + nameLen));\n if ((versionMadeBy >> 8) === 3) { // unix host\n const unixMode = (externalAttrs >>> 16) & 0xffff;\n if ((unixMode & 0o170000) === 0o120000) names.add(name);\n }\n p += 46 + nameLen + extraLen + commentLen;\n }\n } catch {\n return names;\n }\n return names;\n}\n\nfunction findEocd(buf: Uint8Array): number {\n const minRecord = 22;\n const lowerBound = Math.max(0, buf.length - (minRecord + 0xffff));\n for (let i = buf.length - minRecord; i >= lowerBound; i--) {\n if (readU32(buf, i) === 0x06054b50) return i;\n }\n return -1;\n}\n\nfunction readU16(buf: Uint8Array, off: number): number {\n return buf[off] | (buf[off + 1] << 8);\n}\n\nfunction readU32(buf: Uint8Array, off: number): number {\n return (buf[off] | (buf[off + 1] << 8) | (buf[off + 2] << 16) | (buf[off + 3] << 24)) >>> 0;\n}\n","// ---------------------------------------------------------------------------\n// Rule-authoring contract (the code-pack compile target).\n//\n// Code packs are written against `@wairon/sdk`, never against wairon core. This\n// is a small, stable, hand-authored facade — deliberately NOT core's fat\n// RuleContext. `defineRule` returns the rule unchanged (identity + type\n// inference); the runtime shape `{ name, description?, codes: string[], check }`\n// is exactly what the core extension loader duck-types.\n// ---------------------------------------------------------------------------\n\n/** Severity of a finding a pack rule emits. */\nexport type RuleSeverity = 'error' | 'warning';\n\n/** A single issue a pack rule reports about the spec tree. */\nexport interface Finding {\n /** Pack-local issue code (surfaced namespaced by wairon, e.g. `<PACK>_<CODE>`). */\n code: string;\n /** 'error' | 'warning'. */\n severity: RuleSeverity;\n /** Human-readable explanation of the violation. */\n message: string;\n /** The spec id the finding is anchored to (optional). */\n specId?: string;\n}\n\n/**\n * A read-only spec node as seen by a pack rule: its id/name plus arbitrary\n * further fields (kept open so the facade stays stable as the spec model grows).\n */\nexport interface RuleSpecNode {\n id: string;\n name?: string;\n [key: string]: unknown;\n}\n\n/**\n * The minimal, stable view of the spec tree a code-pack rule inspects. A rule\n * reads these collections and returns findings — it never mutates state and\n * never reaches into wairon core internals.\n */\nexport interface RuleContext {\n /** The L0 system spec. */\n system: RuleSpecNode;\n /** All L1 subsystem specs. */\n subsystems: RuleSpecNode[];\n /** All L2 component specs. */\n components: RuleSpecNode[];\n /** All L3 interface specs. */\n interfaces: RuleSpecNode[];\n /** All L4 implementation specs. */\n implementations: RuleSpecNode[];\n /** All shared type/value-object specs. */\n types: RuleSpecNode[];\n}\n\n/**\n * A programmatic conformance rule shipped by a code pack. Its runtime shape —\n * `{ name, description?, codes: string[], check }` — is what wairon's extension\n * loader duck-types when it loads a `pack.cjs`.\n */\nexport interface SddRule {\n /** Stable rule id (kebab-case), e.g. \"my-portal-transport\". */\n name: string;\n /** One-line description of what the rule enforces and why. */\n description?: string;\n /** The issue codes this rule can emit. */\n codes: string[];\n /** Inspect the spec tree and return findings (empty when clean). */\n check(ctx: RuleContext): Finding[];\n}\n\n/**\n * Author an SddRule with full type inference. Returns the rule unchanged — it\n * exists purely so code packs get typed authoring without importing anything\n * from wairon core.\n */\nexport function defineRule(rule: SddRule): SddRule {\n return rule;\n}\n"],"mappings":"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","names":["exports","module","buildPack","buildTreeArchive","extractPack","extractTreeArchive","inspectArchive","inspectTreeArchive","readPack","scaffoldPack","path","import_js_yaml","yamlLoad","yamlDump","path","import_js_yaml","import_crypto","SUPPORTED_FORMAT_VERSION","yamlLoad","validateEnvelope","yamlDump","isSymlinkOrNonRegular","isStructurallyUnsafePath","rejectUnsafe","normalizeRelPath","escapesDestination","pathDepth","compressionRatio","sha256","canonicalDigestBytes","isBelow","parseSemverCore","relative","slug","yamlLoad","scaffoldPack","buildPack","inspectArchive","readPack","extractPack","buildTreeArchive","inspectTreeArchive","extractTreeArchive"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wairon/sdk",
|
|
3
|
-
"version": "6.7.4-dev.
|
|
3
|
+
"version": "6.7.4-dev.10",
|
|
4
4
|
"description": "Experimental: wairon pack-archive (.wpack) format authority and authoring toolkit — scaffold, build, inspect, and safely extract wairon extension packs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wairon",
|