superbee 0.4.3-pre.9 → 0.4.4-pre.1
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/SKILL.md +2 -2
- package/dist/portable-export.mjs +2 -0
- package/dist/publication-bridge.mjs +839 -458
- package/dist/publication.mjs +774 -422
- package/dist/superbee.mjs +102961 -89239
- package/package.json +1 -2
- package/references/author-an-integration.md +192 -0
- package/references/hosted-checkout.md +68 -8
- package/references/integrations/rest-json-authoring/README.md +24 -0
- package/references/integrations/rest-json-authoring/fixture/fixture.json +2466 -0
- package/references/integrations/rest-json-authoring/recipe/connectors/tickets.md +42 -0
- package/references/integrations/rest-json-authoring/recipe/conventions/ticket.md +15 -0
- package/references/integrations/rest-json-authoring/recipe/recipe.md +13 -0
- package/references/modeling-and-delivery.md +3 -0
- package/references/sample-bundle/references/okf-spec.md +8 -2
|
@@ -920,25 +920,25 @@ var require_pairs = __commonJS({
|
|
|
920
920
|
var _toString = Object.prototype.toString;
|
|
921
921
|
function resolveYamlPairs(data) {
|
|
922
922
|
if (data === null) return true;
|
|
923
|
-
var index, length, pair,
|
|
923
|
+
var index, length, pair, keys2, result, object = data;
|
|
924
924
|
result = new Array(object.length);
|
|
925
925
|
for (index = 0, length = object.length; index < length; index += 1) {
|
|
926
926
|
pair = object[index];
|
|
927
927
|
if (_toString.call(pair) !== "[object Object]") return false;
|
|
928
|
-
|
|
929
|
-
if (
|
|
930
|
-
result[index] = [
|
|
928
|
+
keys2 = Object.keys(pair);
|
|
929
|
+
if (keys2.length !== 1) return false;
|
|
930
|
+
result[index] = [keys2[0], pair[keys2[0]]];
|
|
931
931
|
}
|
|
932
932
|
return true;
|
|
933
933
|
}
|
|
934
934
|
function constructYamlPairs(data) {
|
|
935
935
|
if (data === null) return [];
|
|
936
|
-
var index, length, pair,
|
|
936
|
+
var index, length, pair, keys2, result, object = data;
|
|
937
937
|
result = new Array(object.length);
|
|
938
938
|
for (index = 0, length = object.length; index < length; index += 1) {
|
|
939
939
|
pair = object[index];
|
|
940
|
-
|
|
941
|
-
result[index] = [
|
|
940
|
+
keys2 = Object.keys(pair);
|
|
941
|
+
result[index] = [keys2[0], pair[keys2[0]]];
|
|
942
942
|
}
|
|
943
943
|
return result;
|
|
944
944
|
}
|
|
@@ -2345,12 +2345,12 @@ var require_dumper = __commonJS({
|
|
|
2345
2345
|
"OFF"
|
|
2346
2346
|
];
|
|
2347
2347
|
function compileStyleMap(schema, map) {
|
|
2348
|
-
var result,
|
|
2348
|
+
var result, keys2, index, length, tag, style, type;
|
|
2349
2349
|
if (map === null) return {};
|
|
2350
2350
|
result = {};
|
|
2351
|
-
|
|
2352
|
-
for (index = 0, length =
|
|
2353
|
-
tag =
|
|
2351
|
+
keys2 = Object.keys(map);
|
|
2352
|
+
for (index = 0, length = keys2.length; index < length; index += 1) {
|
|
2353
|
+
tag = keys2[index];
|
|
2354
2354
|
style = String(map[tag]);
|
|
2355
2355
|
if (tag.slice(0, 2) === "!!") {
|
|
2356
2356
|
tag = "tag:yaml.org,2002:" + tag.slice(2);
|
|
@@ -2874,7 +2874,38 @@ import { createHash as createHash3 } from "node:crypto";
|
|
|
2874
2874
|
// ../core/src/backend.ts
|
|
2875
2875
|
import path3 from "node:path";
|
|
2876
2876
|
|
|
2877
|
-
// ../core/src/
|
|
2877
|
+
// ../core/src/errors.ts
|
|
2878
|
+
var InvalidInputError = class extends Error {
|
|
2879
|
+
constructor(message) {
|
|
2880
|
+
super(message);
|
|
2881
|
+
this.name = "InvalidInputError";
|
|
2882
|
+
}
|
|
2883
|
+
};
|
|
2884
|
+
var FilesystemIdentityAliasError = class extends InvalidInputError {
|
|
2885
|
+
rel;
|
|
2886
|
+
segment;
|
|
2887
|
+
constructor(rel, segment) {
|
|
2888
|
+
super(
|
|
2889
|
+
`Path '${rel}' does not match the exact spelling of an existing filesystem entry at segment '${segment}'; ids that differ only by case or Unicode normalization cannot share one file.`
|
|
2890
|
+
);
|
|
2891
|
+
this.name = "FilesystemIdentityAliasError";
|
|
2892
|
+
this.rel = rel;
|
|
2893
|
+
this.segment = segment;
|
|
2894
|
+
}
|
|
2895
|
+
};
|
|
2896
|
+
var ConcurrentReplacementError = class extends Error {
|
|
2897
|
+
rel;
|
|
2898
|
+
/** Optional bounded backoff hint for a transient host condition; ordinary observation races use zero. */
|
|
2899
|
+
retryAfterMs;
|
|
2900
|
+
constructor(rel, attempts, retryAfterMs = 0) {
|
|
2901
|
+
super(`Path '${rel}' could not be bound to one stable entry during ${attempts} filesystem attempt(s); retry.`);
|
|
2902
|
+
this.name = "ConcurrentReplacementError";
|
|
2903
|
+
this.rel = rel;
|
|
2904
|
+
this.retryAfterMs = retryAfterMs;
|
|
2905
|
+
}
|
|
2906
|
+
};
|
|
2907
|
+
|
|
2908
|
+
// ../core/src/portable-frontmatter.ts
|
|
2878
2909
|
var import_js_yaml = __toESM(require_js_yaml2(), 1);
|
|
2879
2910
|
|
|
2880
2911
|
// ../core/src/frontmatter-contract.ts
|
|
@@ -2922,261 +2953,448 @@ function splitLeadingFrontmatter(raw, context) {
|
|
|
2922
2953
|
throw new MalformedDocumentError(context, new Error("unterminated YAML frontmatter delimiter"));
|
|
2923
2954
|
}
|
|
2924
2955
|
|
|
2925
|
-
// ../core/src/frontmatter.ts
|
|
2926
|
-
|
|
2927
|
-
function requireYamlTimestampType() {
|
|
2928
|
-
const type = import_js_yaml.default.DEFAULT_SAFE_SCHEMA.implicit.find(
|
|
2929
|
-
(candidate) => candidate.tag === YAML_TIMESTAMP_TAG
|
|
2930
|
-
);
|
|
2931
|
-
if (!type) throw new Error("js-yaml safe schema is missing its timestamp type");
|
|
2932
|
-
return type;
|
|
2933
|
-
}
|
|
2934
|
-
var yamlTimestampType = requireYamlTimestampType();
|
|
2935
|
-
var stringTimestampType = new import_js_yaml.default.Type(YAML_TIMESTAMP_TAG, {
|
|
2936
|
-
kind: "scalar",
|
|
2937
|
-
resolve: (value) => yamlTimestampType.resolve(value),
|
|
2938
|
-
construct: (value) => value
|
|
2939
|
-
});
|
|
2940
|
-
var losslessDateSchema = new import_js_yaml.default.Schema({
|
|
2941
|
-
include: [import_js_yaml.default.DEFAULT_SAFE_SCHEMA],
|
|
2942
|
-
implicit: [stringTimestampType]
|
|
2943
|
-
});
|
|
2944
|
-
var yamlEngine = {
|
|
2945
|
-
parse(input) {
|
|
2946
|
-
return import_js_yaml.default.safeLoad(input, { schema: losslessDateSchema }) ?? {};
|
|
2947
|
-
}
|
|
2948
|
-
};
|
|
2949
|
-
function normalizeFrontmatter(data, okfVersion) {
|
|
2950
|
-
const out = { ...data };
|
|
2951
|
-
if (okfVersion === "0.2") return out;
|
|
2952
|
-
const value = out.timestamp;
|
|
2953
|
-
if (value instanceof Date) {
|
|
2954
|
-
out.timestamp = value.toISOString();
|
|
2955
|
-
} else if (typeof value === "number" && Number.isFinite(value)) {
|
|
2956
|
-
out.timestamp = new Date(value).toISOString();
|
|
2957
|
-
} else if (typeof value === "string" && yamlTimestampType.resolve(value)) {
|
|
2958
|
-
const parsed = yamlTimestampType.construct(value);
|
|
2959
|
-
if (parsed instanceof Date) out.timestamp = parsed.toISOString();
|
|
2960
|
-
}
|
|
2961
|
-
return out;
|
|
2962
|
-
}
|
|
2963
|
-
function parseMarkdown(raw, context, options = {}) {
|
|
2956
|
+
// ../core/src/portable-frontmatter.ts
|
|
2957
|
+
function parseLeadingFrontmatter(raw, context) {
|
|
2964
2958
|
const split = splitLeadingFrontmatter(raw, context);
|
|
2965
|
-
if (!("yamlSource" in split)) return {
|
|
2966
|
-
return { frontmatter: parseFrontmatter(split.yamlSource, context, options), body: split.body };
|
|
2967
|
-
}
|
|
2968
|
-
function parseFrontmatter(source, context, options = {}) {
|
|
2969
|
-
let parsed;
|
|
2959
|
+
if (!("yamlSource" in split)) return {};
|
|
2970
2960
|
try {
|
|
2971
|
-
parsed =
|
|
2972
|
-
|
|
2973
|
-
|
|
2961
|
+
const parsed = import_js_yaml.default.safeLoad(split.yamlSource);
|
|
2962
|
+
if (parsed === void 0 || parsed === null) return {};
|
|
2963
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2964
|
+
throw new TypeError("YAML frontmatter must be a mapping");
|
|
2965
|
+
}
|
|
2966
|
+
return parsed;
|
|
2967
|
+
} catch (error) {
|
|
2968
|
+
if (error instanceof MalformedDocumentError) throw error;
|
|
2969
|
+
throw new MalformedDocumentError(context, error);
|
|
2974
2970
|
}
|
|
2975
|
-
return normalizeFrontmatter(parsed, options.okfVersion);
|
|
2976
2971
|
}
|
|
2977
|
-
|
|
2978
|
-
|
|
2972
|
+
|
|
2973
|
+
// ../core/src/paths.ts
|
|
2974
|
+
var RESERVED_FILENAMES = ["index.md", "log.md"];
|
|
2975
|
+
function compareStorageKeys(a, b) {
|
|
2976
|
+
const primary = a.localeCompare(b);
|
|
2977
|
+
if (primary !== 0 || a === b) return primary;
|
|
2978
|
+
const left = Array.from(a, (character) => character.codePointAt(0));
|
|
2979
|
+
const right = Array.from(b, (character) => character.codePointAt(0));
|
|
2980
|
+
for (let i = 0; i < Math.min(left.length, right.length); i++) {
|
|
2981
|
+
if (left[i] !== right[i]) return left[i] - right[i];
|
|
2982
|
+
}
|
|
2983
|
+
return left.length - right.length;
|
|
2979
2984
|
}
|
|
2980
|
-
function
|
|
2981
|
-
|
|
2982
|
-
|
|
2985
|
+
function assertPortablePath(value, label) {
|
|
2986
|
+
if (/[\u0000-\u001f\u007f]/u.test(value) || /^[a-z]:/i.test(value)) {
|
|
2987
|
+
throw new InvalidInputError(`${label} must not contain controls or start with a drive prefix.`);
|
|
2988
|
+
}
|
|
2989
|
+
if (value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
2990
|
+
throw new InvalidInputError(`${label} must be canonical and bundle-relative.`);
|
|
2991
|
+
}
|
|
2983
2992
|
}
|
|
2984
|
-
function
|
|
2985
|
-
|
|
2993
|
+
function assertSafeReservedFilename(name) {
|
|
2994
|
+
if (!RESERVED_FILENAMES.includes(name)) {
|
|
2995
|
+
throw new InvalidInputError("Reserved filename must be index.md or log.md.");
|
|
2996
|
+
}
|
|
2986
2997
|
}
|
|
2987
|
-
function
|
|
2988
|
-
|
|
2989
|
-
const newline = (value) => value.endsWith("\n") ? value : `${value}
|
|
2990
|
-
`;
|
|
2991
|
-
if (dumped === "{}") return normalizeDocumentBodyForStorage(content);
|
|
2992
|
-
return `---
|
|
2993
|
-
${newline(dumped)}---
|
|
2994
|
-
${normalizeDocumentBodyForStorage(content)}`;
|
|
2998
|
+
function toPosix(p) {
|
|
2999
|
+
return p.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
|
|
2995
3000
|
}
|
|
2996
|
-
function
|
|
2997
|
-
|
|
3001
|
+
function isReservedFile(relPath) {
|
|
3002
|
+
const base = toPosix(relPath).split("/").pop() ?? "";
|
|
3003
|
+
return RESERVED_FILENAMES.includes(base);
|
|
2998
3004
|
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
const generated = frontmatter2.generated;
|
|
3003
|
-
if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
|
|
3004
|
-
return "timestamp";
|
|
3005
|
+
function conceptIdFromPath(relPath) {
|
|
3006
|
+
const norm = toPosix(relPath).replace(/^\.?\//, "").split("/").filter((segment) => segment !== ".").join("/");
|
|
3007
|
+
return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
|
|
3005
3008
|
}
|
|
3006
|
-
function
|
|
3007
|
-
|
|
3009
|
+
function pathFromConceptId(id) {
|
|
3010
|
+
assertSafeConceptId(id);
|
|
3011
|
+
return `${id}.md`;
|
|
3008
3012
|
}
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
constructor(message) {
|
|
3013
|
-
super(message);
|
|
3014
|
-
this.name = "InvalidInputError";
|
|
3013
|
+
function assertSafeConceptId(id) {
|
|
3014
|
+
if (typeof id !== "string" || id.trim() === "") {
|
|
3015
|
+
throw new InvalidInputError("Concept id must be a non-empty string.");
|
|
3015
3016
|
}
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
super(
|
|
3022
|
-
`Path '${rel}' does not match the exact spelling of an existing filesystem entry at segment '${segment}'; ids that differ only by case or Unicode normalization cannot share one file.`
|
|
3017
|
+
assertPortablePath(id, "Concept id");
|
|
3018
|
+
const segments = id.split("/");
|
|
3019
|
+
if (segments.slice(0, -1).some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
3020
|
+
throw new InvalidInputError(
|
|
3021
|
+
`Concept id must not contain a non-final segment ending in '.md': '${id}' (it collides with a concept file at that path).`
|
|
3023
3022
|
);
|
|
3024
|
-
this.name = "FilesystemIdentityAliasError";
|
|
3025
|
-
this.rel = rel;
|
|
3026
|
-
this.segment = segment;
|
|
3027
3023
|
}
|
|
3028
|
-
}
|
|
3029
|
-
var
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
super(`Path '${rel}' could not be bound to one stable entry during ${attempts} filesystem attempt(s); retry.`);
|
|
3035
|
-
this.name = "ConcurrentReplacementError";
|
|
3036
|
-
this.rel = rel;
|
|
3037
|
-
this.retryAfterMs = retryAfterMs;
|
|
3024
|
+
}
|
|
3025
|
+
var FORMAT_AT_EDGE = new RegExp("^\\p{Cf}|\\p{Cf}$", "u");
|
|
3026
|
+
var FORMAT_INSIDE = new RegExp("(?![\\u200c\\u200d])\\p{Cf}", "u");
|
|
3027
|
+
function assertSafeBlobKey(key) {
|
|
3028
|
+
if (typeof key !== "string" || key.trim() === "") {
|
|
3029
|
+
throw new InvalidInputError("Blob key must be a non-empty string.");
|
|
3038
3030
|
}
|
|
3039
|
-
|
|
3031
|
+
assertPortablePath(key, "Blob key");
|
|
3032
|
+
const segments = key.split("/");
|
|
3033
|
+
if (segments.some((seg) => seg.startsWith("."))) {
|
|
3034
|
+
throw new InvalidInputError(`Blob key must not contain dot-prefixed segments: '${key}'.`);
|
|
3035
|
+
}
|
|
3036
|
+
if (segments.some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
3037
|
+
throw new InvalidInputError(
|
|
3038
|
+
`Blob key '${key}' has a path segment ending in '.md' (checked case-insensitively, at any depth), which collides with the concept-document namespace \u2014 write it as a doc instead.`
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
function assertSafeReservedDir(dir) {
|
|
3043
|
+
if (typeof dir !== "string") {
|
|
3044
|
+
throw new InvalidInputError("Reserved-file directory must be a string.");
|
|
3045
|
+
}
|
|
3046
|
+
if (dir !== "") assertPortablePath(dir, "Reserved-file directory");
|
|
3047
|
+
}
|
|
3040
3048
|
|
|
3041
|
-
// ../core/src/
|
|
3042
|
-
var
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3049
|
+
// ../core/src/sha256.ts
|
|
3050
|
+
var K = new Uint32Array([
|
|
3051
|
+
1116352408,
|
|
3052
|
+
1899447441,
|
|
3053
|
+
3049323471,
|
|
3054
|
+
3921009573,
|
|
3055
|
+
961987163,
|
|
3056
|
+
1508970993,
|
|
3057
|
+
2453635748,
|
|
3058
|
+
2870763221,
|
|
3059
|
+
3624381080,
|
|
3060
|
+
310598401,
|
|
3061
|
+
607225278,
|
|
3062
|
+
1426881987,
|
|
3063
|
+
1925078388,
|
|
3064
|
+
2162078206,
|
|
3065
|
+
2614888103,
|
|
3066
|
+
3248222580,
|
|
3067
|
+
3835390401,
|
|
3068
|
+
4022224774,
|
|
3069
|
+
264347078,
|
|
3070
|
+
604807628,
|
|
3071
|
+
770255983,
|
|
3072
|
+
1249150122,
|
|
3073
|
+
1555081692,
|
|
3074
|
+
1996064986,
|
|
3075
|
+
2554220882,
|
|
3076
|
+
2821834349,
|
|
3077
|
+
2952996808,
|
|
3078
|
+
3210313671,
|
|
3079
|
+
3336571891,
|
|
3080
|
+
3584528711,
|
|
3081
|
+
113926993,
|
|
3082
|
+
338241895,
|
|
3083
|
+
666307205,
|
|
3084
|
+
773529912,
|
|
3085
|
+
1294757372,
|
|
3086
|
+
1396182291,
|
|
3087
|
+
1695183700,
|
|
3088
|
+
1986661051,
|
|
3089
|
+
2177026350,
|
|
3090
|
+
2456956037,
|
|
3091
|
+
2730485921,
|
|
3092
|
+
2820302411,
|
|
3093
|
+
3259730800,
|
|
3094
|
+
3345764771,
|
|
3095
|
+
3516065817,
|
|
3096
|
+
3600352804,
|
|
3097
|
+
4094571909,
|
|
3098
|
+
275423344,
|
|
3099
|
+
430227734,
|
|
3100
|
+
506948616,
|
|
3101
|
+
659060556,
|
|
3102
|
+
883997877,
|
|
3103
|
+
958139571,
|
|
3104
|
+
1322822218,
|
|
3105
|
+
1537002063,
|
|
3106
|
+
1747873779,
|
|
3107
|
+
1955562222,
|
|
3108
|
+
2024104815,
|
|
3109
|
+
2227730452,
|
|
3110
|
+
2361852424,
|
|
3111
|
+
2428436474,
|
|
3112
|
+
2756734187,
|
|
3113
|
+
3204031479,
|
|
3114
|
+
3329325298
|
|
3046
3115
|
]);
|
|
3047
|
-
var
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
if (!zulu) {
|
|
3065
|
-
const offsetHours = Number(oh);
|
|
3066
|
-
const offsetMins = Number(om);
|
|
3067
|
-
if (offsetHours > 23 || offsetMins > 59) return null;
|
|
3068
|
-
offsetMinutes = (sign === "-" ? -1 : 1) * (offsetHours * 60 + offsetMins);
|
|
3116
|
+
var INITIAL_STATE = new Uint32Array([
|
|
3117
|
+
1779033703,
|
|
3118
|
+
3144134277,
|
|
3119
|
+
1013904242,
|
|
3120
|
+
2773480762,
|
|
3121
|
+
1359893119,
|
|
3122
|
+
2600822924,
|
|
3123
|
+
528734635,
|
|
3124
|
+
1541459225
|
|
3125
|
+
]);
|
|
3126
|
+
var encoder = new TextEncoder();
|
|
3127
|
+
function rotr(value, bits) {
|
|
3128
|
+
return value >>> bits | value << 32 - bits;
|
|
3129
|
+
}
|
|
3130
|
+
function compress(h, w, view, offset) {
|
|
3131
|
+
for (let i = 0; i < 16; i++) {
|
|
3132
|
+
w[i] = view.getUint32(offset + i * 4);
|
|
3069
3133
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3134
|
+
for (let i = 16; i < 64; i++) {
|
|
3135
|
+
const w15 = w[i - 15];
|
|
3136
|
+
const w2 = w[i - 2];
|
|
3137
|
+
const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ w15 >>> 3;
|
|
3138
|
+
const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ w2 >>> 10;
|
|
3139
|
+
w[i] = w[i - 16] + s0 + w[i - 7] + s1 >>> 0;
|
|
3140
|
+
}
|
|
3141
|
+
let a = h[0];
|
|
3142
|
+
let b = h[1];
|
|
3143
|
+
let c = h[2];
|
|
3144
|
+
let d = h[3];
|
|
3145
|
+
let e = h[4];
|
|
3146
|
+
let f = h[5];
|
|
3147
|
+
let g = h[6];
|
|
3148
|
+
let hh = h[7];
|
|
3149
|
+
for (let i = 0; i < 64; i++) {
|
|
3150
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
3151
|
+
const ch = e & f ^ ~e & g;
|
|
3152
|
+
const t1 = hh + S1 + ch + K[i] + w[i] >>> 0;
|
|
3153
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
3154
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
3155
|
+
const t2 = S0 + maj >>> 0;
|
|
3156
|
+
hh = g;
|
|
3157
|
+
g = f;
|
|
3158
|
+
f = e;
|
|
3159
|
+
e = d + t1 >>> 0;
|
|
3160
|
+
d = c;
|
|
3161
|
+
c = b;
|
|
3162
|
+
b = a;
|
|
3163
|
+
a = t1 + t2 >>> 0;
|
|
3164
|
+
}
|
|
3165
|
+
h[0] = h[0] + a >>> 0;
|
|
3166
|
+
h[1] = h[1] + b >>> 0;
|
|
3167
|
+
h[2] = h[2] + c >>> 0;
|
|
3168
|
+
h[3] = h[3] + d >>> 0;
|
|
3169
|
+
h[4] = h[4] + e >>> 0;
|
|
3170
|
+
h[5] = h[5] + f >>> 0;
|
|
3171
|
+
h[6] = h[6] + g >>> 0;
|
|
3172
|
+
h[7] = h[7] + hh >>> 0;
|
|
3076
3173
|
}
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3174
|
+
function sha256HexOfBytes(bytes) {
|
|
3175
|
+
const h = new Uint32Array(INITIAL_STATE);
|
|
3176
|
+
const w = new Uint32Array(64);
|
|
3177
|
+
const length = bytes.byteLength;
|
|
3178
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, length);
|
|
3179
|
+
const fullBlocks = length >>> 6;
|
|
3180
|
+
for (let block = 0; block < fullBlocks; block++) {
|
|
3181
|
+
compress(h, w, view, block * 64);
|
|
3084
3182
|
}
|
|
3085
|
-
|
|
3086
|
-
|
|
3183
|
+
const remaining = length - fullBlocks * 64;
|
|
3184
|
+
const tail = new Uint8Array(remaining + 1 + 8 > 64 ? 128 : 64);
|
|
3185
|
+
tail.set(bytes.subarray(fullBlocks * 64));
|
|
3186
|
+
tail[remaining] = 128;
|
|
3187
|
+
const tailView = new DataView(tail.buffer);
|
|
3188
|
+
const bitLengthHigh = Math.floor(length / 536870912);
|
|
3189
|
+
const bitLengthLow = length << 3 >>> 0;
|
|
3190
|
+
tailView.setUint32(tail.length - 8, bitLengthHigh);
|
|
3191
|
+
tailView.setUint32(tail.length - 4, bitLengthLow);
|
|
3192
|
+
for (let offset = 0; offset < tail.length; offset += 64) {
|
|
3193
|
+
compress(h, w, tailView, offset);
|
|
3087
3194
|
}
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3195
|
+
let hex = "";
|
|
3196
|
+
for (let i = 0; i < 8; i++) {
|
|
3197
|
+
hex += h[i].toString(16).padStart(8, "0");
|
|
3198
|
+
}
|
|
3199
|
+
return hex;
|
|
3091
3200
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
var OKF_LIFECYCLE_STATUSES = Object.freeze(["draft", "stable", "deprecated"]);
|
|
3095
|
-
function isOkfLifecycleStatus(value) {
|
|
3096
|
-
return typeof value === "string" && OKF_LIFECYCLE_STATUSES.includes(value);
|
|
3201
|
+
function sha256HexOfUtf8(input) {
|
|
3202
|
+
return sha256HexOfBytes(encoder.encode(input));
|
|
3097
3203
|
}
|
|
3098
3204
|
|
|
3099
|
-
// ../core/src/
|
|
3100
|
-
var
|
|
3101
|
-
|
|
3102
|
-
|
|
3205
|
+
// ../core/src/inventory-guard.ts
|
|
3206
|
+
var INVENTORY_GUARD_DOMAIN = "cooperating-local-writers-v1";
|
|
3207
|
+
var InventoryGuardUnsupported = class extends Error {
|
|
3208
|
+
written = false;
|
|
3209
|
+
reason;
|
|
3210
|
+
constructor(reason) {
|
|
3211
|
+
super(`Inventory guard unsupported: ${reason}`);
|
|
3212
|
+
this.name = "InventoryGuardUnsupported";
|
|
3213
|
+
this.reason = reason;
|
|
3214
|
+
}
|
|
3215
|
+
};
|
|
3216
|
+
var InventoryGuardConflict = class extends Error {
|
|
3217
|
+
written = false;
|
|
3218
|
+
reason;
|
|
3219
|
+
constructor(reason) {
|
|
3220
|
+
super(`Inventory guard premise changed: ${reason}`);
|
|
3221
|
+
this.name = "InventoryGuardConflict";
|
|
3222
|
+
this.reason = reason;
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
var capabilityOwners = /* @__PURE__ */ new WeakMap();
|
|
3226
|
+
function bindInventoryGuard(owner, guard) {
|
|
3227
|
+
capabilityOwners.set(guard, owner);
|
|
3228
|
+
return guard;
|
|
3229
|
+
}
|
|
3230
|
+
function assertInventoryGuardBound(count) {
|
|
3231
|
+
if (count > 1e4) throw new InventoryGuardUnsupported("inventory_document_bound");
|
|
3232
|
+
}
|
|
3233
|
+
function copyData(value, active = /* @__PURE__ */ new Set(), budget = { nodes: 1e5 }) {
|
|
3234
|
+
if (--budget.nodes < 0) throw new InvalidInputError("Inventory guard input exceeds its data bound.");
|
|
3235
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
3236
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
3237
|
+
if (typeof value !== "object") throw new InvalidInputError("Inventory guard accepts finite plain data only.");
|
|
3238
|
+
if (active.has(value)) throw new InvalidInputError("Inventory guard input is cyclic.");
|
|
3239
|
+
const array = Array.isArray(value);
|
|
3240
|
+
if (Object.getPrototypeOf(value) !== (array ? Array.prototype : Object.prototype) && Object.getPrototypeOf(value) !== null) {
|
|
3241
|
+
throw new InvalidInputError("Inventory guard accepts plain objects and arrays only.");
|
|
3242
|
+
}
|
|
3243
|
+
active.add(value);
|
|
3244
|
+
const result = array ? [] : /* @__PURE__ */ Object.create(null);
|
|
3245
|
+
if (array && Object.keys(value).length !== value.length) throw new InvalidInputError("Inventory guard input cannot carry sparse arrays or extra keys.");
|
|
3246
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
3247
|
+
if (array && key === "length") continue;
|
|
3248
|
+
if (array && (typeof key !== "string" || !/^(0|[1-9][0-9]*)$/.test(key))) throw new InvalidInputError("Inventory guard arrays require indexed data only.");
|
|
3249
|
+
if (typeof key !== "string") throw new InvalidInputError("Inventory guard input cannot carry symbol keys.");
|
|
3250
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
3251
|
+
if (!property.enumerable || !("value" in property)) throw new InvalidInputError("Inventory guard input cannot carry accessors or hidden data.");
|
|
3252
|
+
Object.defineProperty(result, key, { value: copyData(property.value, active, budget), enumerable: true, configurable: true, writable: true });
|
|
3253
|
+
}
|
|
3254
|
+
if (array && result.length !== value.length) throw new InvalidInputError("Inventory guard input cannot carry sparse arrays.");
|
|
3255
|
+
active.delete(value);
|
|
3256
|
+
return result;
|
|
3257
|
+
}
|
|
3258
|
+
function record(value) {
|
|
3259
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new InvalidInputError("Inventory guard expected an object.");
|
|
3260
|
+
return value;
|
|
3103
3261
|
}
|
|
3104
|
-
function
|
|
3105
|
-
|
|
3262
|
+
function keys(value, allowed) {
|
|
3263
|
+
if (Object.keys(value).some((key) => !allowed.includes(key))) throw new InvalidInputError("Inventory guard input has unsupported fields.");
|
|
3264
|
+
}
|
|
3265
|
+
function version(value) {
|
|
3266
|
+
if (typeof value !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value)) throw new InvalidInputError("Inventory guard requires exact content versions.");
|
|
3267
|
+
}
|
|
3268
|
+
function captureInventoryGuardRequest(input) {
|
|
3269
|
+
const data = record(copyData(input));
|
|
3270
|
+
keys(data, ["target", "domain", "inventory", "id", "expectedVersion", "doc", "options"]);
|
|
3271
|
+
const target = record(data.target);
|
|
3272
|
+
keys(target, ["contract", "domain", "adapter", "store", "root_version", "edition"]);
|
|
3273
|
+
if (target.contract !== "inventory-guard/v1" || target.domain !== INVENTORY_GUARD_DOMAIN || data.domain !== INVENTORY_GUARD_DOMAIN) {
|
|
3274
|
+
throw new InventoryGuardUnsupported("domain_or_contract");
|
|
3275
|
+
}
|
|
3276
|
+
if (!["memory", "filesystem"].includes(String(target.adapter)) || typeof target.store !== "string" || target.store.length === 0 || !["0.1", "0.2"].includes(String(target.edition))) throw new InvalidInputError("Invalid inventory guard target.");
|
|
3277
|
+
version(target.root_version);
|
|
3278
|
+
if (typeof data.id !== "string") throw new InvalidInputError("Inventory guard requires a target id.");
|
|
3279
|
+
assertSafeConceptId(data.id);
|
|
3280
|
+
if (isReservedFile(pathFromConceptId(data.id))) throw new InvalidInputError("Inventory guard target must be a concept.");
|
|
3281
|
+
version(data.expectedVersion);
|
|
3282
|
+
if (!Array.isArray(data.inventory)) throw new InvalidInputError("Inventory guard requires a complete inventory.");
|
|
3283
|
+
assertInventoryGuardBound(data.inventory.length);
|
|
3284
|
+
let previous;
|
|
3285
|
+
for (const raw of data.inventory) {
|
|
3286
|
+
const row = record(raw);
|
|
3287
|
+
keys(row, ["id", "version"]);
|
|
3288
|
+
if (typeof row.id !== "string") throw new InvalidInputError("Inventory guard inventory id is invalid.");
|
|
3289
|
+
assertSafeConceptId(row.id);
|
|
3290
|
+
if (isReservedFile(pathFromConceptId(row.id)) || previous !== void 0 && compareStorageKeys(previous, row.id) >= 0) throw new InvalidInputError("Inventory guard inventory must be sorted, unique concepts.");
|
|
3291
|
+
version(row.version);
|
|
3292
|
+
previous = row.id;
|
|
3293
|
+
}
|
|
3294
|
+
if (!data.inventory.some((row) => row.id === data.id && row.version === data.expectedVersion)) throw new InvalidInputError("Inventory guard target/version is missing from inventory.");
|
|
3295
|
+
const doc = record(data.doc);
|
|
3296
|
+
keys(doc, ["id", "frontmatter", "body"]);
|
|
3297
|
+
if (doc.id !== data.id || typeof doc.body !== "string") throw new InvalidInputError("Inventory guard candidate identity/body is invalid.");
|
|
3298
|
+
record(doc.frontmatter);
|
|
3299
|
+
if (data.options !== void 0) {
|
|
3300
|
+
const options = record(data.options);
|
|
3301
|
+
keys(options, ["actor", "agent"]);
|
|
3302
|
+
if (Object.values(options).some((value) => typeof value !== "string")) throw new InvalidInputError("Inventory guard attribution must be strings.");
|
|
3303
|
+
}
|
|
3304
|
+
return data;
|
|
3305
|
+
}
|
|
3306
|
+
function guardEdition(content) {
|
|
3307
|
+
if (content === null) throw new InventoryGuardUnsupported("root_metadata_absent");
|
|
3308
|
+
const edition = parseLeadingFrontmatter(content, "index.md").okf_version;
|
|
3309
|
+
if (edition !== "0.1" && edition !== "0.2") throw new InventoryGuardUnsupported("root_edition_unestablished");
|
|
3310
|
+
return edition;
|
|
3311
|
+
}
|
|
3312
|
+
function compareInventoryPremises(expected, current, inventory) {
|
|
3313
|
+
if (expected.target.adapter !== current.adapter || expected.target.store !== current.store) throw new InventoryGuardConflict("identity");
|
|
3314
|
+
if (expected.target.edition !== current.edition) throw new InventoryGuardConflict("edition");
|
|
3315
|
+
if (expected.target.root_version !== current.root_version) throw new InventoryGuardConflict("root_metadata");
|
|
3316
|
+
if (expected.inventory.length !== inventory.length || expected.inventory.some((row, index) => row.id !== inventory[index]?.id)) throw new InventoryGuardConflict("membership");
|
|
3317
|
+
if (expected.inventory.some((row, index) => row.version !== inventory[index].version)) throw new InventoryGuardConflict("version");
|
|
3318
|
+
if (!inventory.some((row) => row.id === expected.id && row.version === expected.expectedVersion)) throw new InventoryGuardConflict("target_version");
|
|
3319
|
+
}
|
|
3320
|
+
function inventoryDigest(inventory) {
|
|
3321
|
+
return `sha256:${sha256HexOfUtf8(JSON.stringify(inventory.map((row) => [row.id, row.version])))}`;
|
|
3106
3322
|
}
|
|
3107
3323
|
|
|
3108
|
-
// ../core/src/
|
|
3109
|
-
var
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
}
|
|
3118
|
-
return left.length - right.length;
|
|
3324
|
+
// ../core/src/frontmatter.ts
|
|
3325
|
+
var import_js_yaml2 = __toESM(require_js_yaml2(), 1);
|
|
3326
|
+
var YAML_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp";
|
|
3327
|
+
function requireYamlTimestampType() {
|
|
3328
|
+
const type = import_js_yaml2.default.DEFAULT_SAFE_SCHEMA.implicit.find(
|
|
3329
|
+
(candidate) => candidate.tag === YAML_TIMESTAMP_TAG
|
|
3330
|
+
);
|
|
3331
|
+
if (!type) throw new Error("js-yaml safe schema is missing its timestamp type");
|
|
3332
|
+
return type;
|
|
3119
3333
|
}
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3334
|
+
var yamlTimestampType = requireYamlTimestampType();
|
|
3335
|
+
var stringTimestampType = new import_js_yaml2.default.Type(YAML_TIMESTAMP_TAG, {
|
|
3336
|
+
kind: "scalar",
|
|
3337
|
+
resolve: (value) => yamlTimestampType.resolve(value),
|
|
3338
|
+
construct: (value) => value
|
|
3339
|
+
});
|
|
3340
|
+
var losslessDateSchema = new import_js_yaml2.default.Schema({
|
|
3341
|
+
include: [import_js_yaml2.default.DEFAULT_SAFE_SCHEMA],
|
|
3342
|
+
implicit: [stringTimestampType]
|
|
3343
|
+
});
|
|
3344
|
+
var yamlEngine = {
|
|
3345
|
+
parse(input) {
|
|
3346
|
+
return import_js_yaml2.default.safeLoad(input, { schema: losslessDateSchema }) ?? {};
|
|
3126
3347
|
}
|
|
3127
|
-
}
|
|
3128
|
-
function
|
|
3129
|
-
|
|
3130
|
-
|
|
3348
|
+
};
|
|
3349
|
+
function normalizeFrontmatter(data, options) {
|
|
3350
|
+
const out = { ...data };
|
|
3351
|
+
if (options.preserveTimestamp || options.okfVersion === "0.2") return out;
|
|
3352
|
+
const value = out.timestamp;
|
|
3353
|
+
if (value instanceof Date) {
|
|
3354
|
+
out.timestamp = value.toISOString();
|
|
3355
|
+
} else if (typeof value === "number" && Number.isFinite(value)) {
|
|
3356
|
+
out.timestamp = new Date(value).toISOString();
|
|
3357
|
+
} else if (typeof value === "string" && yamlTimestampType.resolve(value)) {
|
|
3358
|
+
const parsed = yamlTimestampType.construct(value);
|
|
3359
|
+
if (parsed instanceof Date) out.timestamp = parsed.toISOString();
|
|
3131
3360
|
}
|
|
3361
|
+
return out;
|
|
3132
3362
|
}
|
|
3133
|
-
function
|
|
3134
|
-
|
|
3363
|
+
function parseMarkdown(raw, context, options = {}) {
|
|
3364
|
+
const split = splitLeadingFrontmatter(raw, context);
|
|
3365
|
+
if (!("yamlSource" in split)) return { frontmatter: {}, body: split.body };
|
|
3366
|
+
return { frontmatter: parseFrontmatter(split.yamlSource, context, options), body: split.body };
|
|
3135
3367
|
}
|
|
3136
|
-
function
|
|
3137
|
-
|
|
3138
|
-
|
|
3368
|
+
function parseFrontmatter(source, context, options = {}) {
|
|
3369
|
+
let parsed;
|
|
3370
|
+
try {
|
|
3371
|
+
parsed = yamlEngine.parse(source);
|
|
3372
|
+
} catch (err) {
|
|
3373
|
+
throw new MalformedDocumentError(context, err);
|
|
3374
|
+
}
|
|
3375
|
+
return normalizeFrontmatter(parsed, options);
|
|
3139
3376
|
}
|
|
3140
|
-
function
|
|
3141
|
-
|
|
3142
|
-
return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
|
|
3377
|
+
function stringifyFrontmatter(data) {
|
|
3378
|
+
return import_js_yaml2.default.safeDump(data).trim();
|
|
3143
3379
|
}
|
|
3144
|
-
function
|
|
3145
|
-
|
|
3146
|
-
|
|
3380
|
+
function normalizeDocumentBodyForStorage(body) {
|
|
3381
|
+
return body.endsWith("\n") ? body : `${body}
|
|
3382
|
+
`;
|
|
3147
3383
|
}
|
|
3148
|
-
function
|
|
3149
|
-
|
|
3150
|
-
throw new InvalidInputError("Concept id must be a non-empty string.");
|
|
3151
|
-
}
|
|
3152
|
-
assertPortablePath(id, "Concept id");
|
|
3153
|
-
const segments = id.split("/");
|
|
3154
|
-
if (segments.slice(0, -1).some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
3155
|
-
throw new InvalidInputError(
|
|
3156
|
-
`Concept id must not contain a non-final segment ending in '.md': '${id}' (it collides with a concept file at that path).`
|
|
3157
|
-
);
|
|
3158
|
-
}
|
|
3384
|
+
function stringifyWithData(data, body) {
|
|
3385
|
+
return stringifyWithSerializedFrontmatter(stringifyFrontmatter(data), body);
|
|
3159
3386
|
}
|
|
3160
|
-
function
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
}
|
|
3169
|
-
if (segments.some((seg) => seg.toLowerCase().endsWith(".md"))) {
|
|
3170
|
-
throw new InvalidInputError(
|
|
3171
|
-
`Blob key '${key}' has a path segment ending in '.md' (checked case-insensitively, at any depth), which collides with the concept-document namespace \u2014 write it as a doc instead.`
|
|
3172
|
-
);
|
|
3173
|
-
}
|
|
3387
|
+
function stringifyWithSerializedFrontmatter(dumped, body) {
|
|
3388
|
+
const content = body ?? "";
|
|
3389
|
+
const newline = (value) => value.endsWith("\n") ? value : `${value}
|
|
3390
|
+
`;
|
|
3391
|
+
if (dumped === "{}") return normalizeDocumentBodyForStorage(content);
|
|
3392
|
+
return `---
|
|
3393
|
+
${newline(dumped)}---
|
|
3394
|
+
${normalizeDocumentBodyForStorage(content)}`;
|
|
3174
3395
|
}
|
|
3175
|
-
function
|
|
3176
|
-
|
|
3177
|
-
throw new InvalidInputError("Reserved-file directory must be a string.");
|
|
3178
|
-
}
|
|
3179
|
-
if (dir !== "") assertPortablePath(dir, "Reserved-file directory");
|
|
3396
|
+
function stringifyDoc(frontmatter2, body) {
|
|
3397
|
+
return stringifyWithData(frontmatter2, body);
|
|
3180
3398
|
}
|
|
3181
3399
|
|
|
3182
3400
|
// ../core/src/links.ts
|
|
@@ -3420,23 +3638,114 @@ function parseLinksFromDoc(doc) {
|
|
|
3420
3638
|
}
|
|
3421
3639
|
return links;
|
|
3422
3640
|
}
|
|
3423
|
-
|
|
3424
|
-
// ../core/src/
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3641
|
+
|
|
3642
|
+
// ../core/src/version-transport.ts
|
|
3643
|
+
function isContentVersion(value) {
|
|
3644
|
+
return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
3645
|
+
}
|
|
3646
|
+
var VersionConflict = class extends Error {
|
|
3647
|
+
name = "VersionConflict";
|
|
3648
|
+
id;
|
|
3649
|
+
expected;
|
|
3650
|
+
actual;
|
|
3651
|
+
constructor(id, expected, actual) {
|
|
3652
|
+
super(
|
|
3653
|
+
`version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
|
|
3654
|
+
);
|
|
3655
|
+
this.id = id;
|
|
3656
|
+
this.expected = expected;
|
|
3657
|
+
this.actual = actual;
|
|
3658
|
+
}
|
|
3659
|
+
};
|
|
3660
|
+
|
|
3661
|
+
// ../core/src/meaningful-change-time.ts
|
|
3662
|
+
function meaningfulChangeTimeField(frontmatter2) {
|
|
3663
|
+
const generated = frontmatter2.generated;
|
|
3664
|
+
if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
|
|
3665
|
+
return "timestamp";
|
|
3666
|
+
}
|
|
3667
|
+
function meaningfulChangeTimeValue(frontmatter2) {
|
|
3668
|
+
return meaningfulChangeTimeField(frontmatter2) === "generated.at" ? frontmatter2.generated.at : frontmatter2.timestamp;
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3671
|
+
// ../core/src/verification.ts
|
|
3672
|
+
var TRUST_TIERS = Object.freeze([
|
|
3673
|
+
"unverified",
|
|
3674
|
+
"machine-confirmed",
|
|
3675
|
+
"human-reviewed"
|
|
3676
|
+
]);
|
|
3677
|
+
var ISO_INSTANT = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(?:([Zz])|([+-])(\d{2})(?::?(\d{2}))?)$/;
|
|
3678
|
+
function parseIsoInstant(raw, rounding = "truncate") {
|
|
3679
|
+
const match = ISO_INSTANT.exec(raw);
|
|
3680
|
+
if (!match) return null;
|
|
3681
|
+
const [, y, mo, d, h, mi, sec = "0", frac = "0", zulu, sign, oh, om = "0"] = match;
|
|
3682
|
+
const year = Number(y);
|
|
3683
|
+
const month = Number(mo);
|
|
3684
|
+
const day = Number(d);
|
|
3685
|
+
const hour = Number(h);
|
|
3686
|
+
const minute = Number(mi);
|
|
3687
|
+
const second = Number(sec);
|
|
3688
|
+
if (month < 1 || month > 12) return null;
|
|
3689
|
+
const probe = /* @__PURE__ */ new Date(0);
|
|
3690
|
+
probe.setUTCFullYear(year, month, 0);
|
|
3691
|
+
if (day < 1 || day > probe.getUTCDate()) return null;
|
|
3692
|
+
if (hour > 23 || minute > 59 || second > 59) return null;
|
|
3693
|
+
let offsetMinutes = 0;
|
|
3694
|
+
if (!zulu) {
|
|
3695
|
+
const offsetHours = Number(oh);
|
|
3696
|
+
const offsetMins = Number(om);
|
|
3697
|
+
if (offsetHours > 23 || offsetMins > 59) return null;
|
|
3698
|
+
offsetMinutes = (sign === "-" ? -1 : 1) * (offsetHours * 60 + offsetMins);
|
|
3699
|
+
}
|
|
3700
|
+
const millis = Number(frac.padEnd(3, "0").slice(0, 3));
|
|
3701
|
+
const instant = /* @__PURE__ */ new Date(0);
|
|
3702
|
+
instant.setUTCFullYear(year, month - 1, day);
|
|
3703
|
+
instant.setUTCHours(hour, minute, second, millis);
|
|
3704
|
+
const remainder = rounding === "ceil" && /[1-9]/.test(frac.slice(3)) ? 1 : 0;
|
|
3705
|
+
return instant.getTime() - offsetMinutes * 6e4 + remainder;
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
// ../core/src/freshness.ts
|
|
3709
|
+
function parseTimestamp(ts, okfVersion) {
|
|
3710
|
+
if (okfVersion === "0.2") return typeof ts === "string" ? parseIsoInstant(ts) : null;
|
|
3711
|
+
if (ts instanceof Date) {
|
|
3712
|
+
const ms2 = ts.getTime();
|
|
3713
|
+
return Number.isNaN(ms2) ? null : ms2;
|
|
3714
|
+
}
|
|
3715
|
+
if (typeof ts === "number") {
|
|
3716
|
+
return Number.isFinite(ts) ? ts : null;
|
|
3717
|
+
}
|
|
3718
|
+
if (typeof ts !== "string" || ts.trim() === "") return null;
|
|
3719
|
+
const ms = Date.parse(ts);
|
|
3720
|
+
return Number.isNaN(ms) ? null : ms;
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3723
|
+
// ../core/src/okf-authored-values.ts
|
|
3724
|
+
function isOkfRecord(value) {
|
|
3725
|
+
if (value === null || typeof value !== "object") return false;
|
|
3726
|
+
const prototype = Object.getPrototypeOf(value);
|
|
3727
|
+
return prototype === Object.prototype || prototype === null;
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
// ../core/src/okf-lifecycle.ts
|
|
3731
|
+
var OKF_LIFECYCLE_STATUSES = Object.freeze(["draft", "stable", "deprecated"]);
|
|
3732
|
+
function isOkfLifecycleStatus(value) {
|
|
3733
|
+
return typeof value === "string" && OKF_LIFECYCLE_STATUSES.includes(value);
|
|
3734
|
+
}
|
|
3735
|
+
|
|
3736
|
+
// ../core/src/okf-standard-fields.ts
|
|
3737
|
+
var OKF_STANDARD_FIELD_NAMES = ["type", "title", "description", "resource", "tags", "status", "sources", "generated", "verified", "stale_after", "usage_window", "runtime", "computation", "parameters", "executor", "attester", "okf_version"];
|
|
3738
|
+
function isOkfStandardField(field) {
|
|
3739
|
+
return OKF_STANDARD_FIELD_NAMES.includes(field);
|
|
3740
|
+
}
|
|
3741
|
+
|
|
3742
|
+
// ../core/src/mutation-attribution.ts
|
|
3743
|
+
var SUPERBEE_UPDATED_BY_FIELD = "superbee_updated_by";
|
|
3744
|
+
function nonEmptyString(value) {
|
|
3745
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
3746
|
+
}
|
|
3747
|
+
function mutationActorFromFrontmatter(frontmatter2) {
|
|
3748
|
+
return nonEmptyString(frontmatter2[SUPERBEE_UPDATED_BY_FIELD]) ?? nonEmptyString(frontmatter2.updated_by) ?? nonEmptyString(frontmatter2.actor);
|
|
3440
3749
|
}
|
|
3441
3750
|
|
|
3442
3751
|
// ../core/src/query-filter.ts
|
|
@@ -3460,13 +3769,22 @@ function matchesFilter(doc, filter) {
|
|
|
3460
3769
|
}
|
|
3461
3770
|
return true;
|
|
3462
3771
|
}
|
|
3463
|
-
function
|
|
3464
|
-
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return
|
|
3772
|
+
function sourceIdentityOf(entry) {
|
|
3773
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return void 0;
|
|
3465
3774
|
const row = entry;
|
|
3775
|
+
const identity = {};
|
|
3776
|
+
for (const key of ["resource", "id"]) {
|
|
3777
|
+
if (Object.hasOwn(row, key) && typeof row[key] === "string") identity[key] = row[key];
|
|
3778
|
+
}
|
|
3779
|
+
return identity;
|
|
3780
|
+
}
|
|
3781
|
+
function matchesSourceIdentity(entry, identity) {
|
|
3782
|
+
const own = sourceIdentityOf(entry);
|
|
3783
|
+
if (!own) return false;
|
|
3466
3784
|
for (const key of ["resource", "id"]) {
|
|
3467
3785
|
const expected = identity[key];
|
|
3468
3786
|
if (expected === void 0) continue;
|
|
3469
|
-
if (
|
|
3787
|
+
if (own[key] === void 0 || own[key] !== expected) return false;
|
|
3470
3788
|
}
|
|
3471
3789
|
return true;
|
|
3472
3790
|
}
|
|
@@ -3535,10 +3853,10 @@ async function queryHeads(backend, filter = {}, options = {}) {
|
|
|
3535
3853
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
3536
3854
|
return rows;
|
|
3537
3855
|
}
|
|
3538
|
-
return (await scanMatching(backend, filter, options.onSkip)).map(({ doc, version }) => ({
|
|
3856
|
+
return (await scanMatching(backend, filter, options.onSkip)).map(({ doc, version: version2 }) => ({
|
|
3539
3857
|
id: doc.id,
|
|
3540
3858
|
frontmatter: doc.frontmatter,
|
|
3541
|
-
version
|
|
3859
|
+
version: version2
|
|
3542
3860
|
}));
|
|
3543
3861
|
}
|
|
3544
3862
|
function normalizeEdgeSelector(raw) {
|
|
@@ -3650,13 +3968,13 @@ function snapshotHostPolicy(input, seen = /* @__PURE__ */ new WeakMap()) {
|
|
|
3650
3968
|
if (existing) return existing;
|
|
3651
3969
|
const result = Array.isArray(input) ? [] : {};
|
|
3652
3970
|
seen.set(input, result);
|
|
3653
|
-
const
|
|
3971
|
+
const keys2 = /* @__PURE__ */ new Set();
|
|
3654
3972
|
for (let owner = input; owner && owner !== Object.prototype && owner !== Array.prototype; owner = Object.getPrototypeOf(owner)) {
|
|
3655
3973
|
for (const key of Reflect.ownKeys(owner)) {
|
|
3656
|
-
if (key !== "constructor" && !(Array.isArray(input) && key === "length"))
|
|
3974
|
+
if (key !== "constructor" && !(Array.isArray(input) && key === "length")) keys2.add(key);
|
|
3657
3975
|
}
|
|
3658
3976
|
}
|
|
3659
|
-
for (const key of
|
|
3977
|
+
for (const key of keys2) {
|
|
3660
3978
|
const value = input[key];
|
|
3661
3979
|
Object.defineProperty(result, key, {
|
|
3662
3980
|
value: typeof value === "function" ? value.bind(result) : value && typeof value === "object" ? snapshotHostPolicy(value, seen) : value,
|
|
@@ -3781,14 +4099,14 @@ async function readOwnerRecord(lockPath) {
|
|
|
3781
4099
|
}
|
|
3782
4100
|
async function resolveOwnerRecord(lockPath, started, waitMs, pollMs) {
|
|
3783
4101
|
while (true) {
|
|
3784
|
-
const
|
|
3785
|
-
if (
|
|
4102
|
+
const record2 = await readOwnerRecord(lockPath);
|
|
4103
|
+
if (record2.state !== "unreadable" || Date.now() - started >= waitMs) return record2;
|
|
3786
4104
|
await delay(pollMs);
|
|
3787
4105
|
}
|
|
3788
4106
|
}
|
|
3789
4107
|
async function readOwner(lockPath) {
|
|
3790
|
-
const
|
|
3791
|
-
return
|
|
4108
|
+
const record2 = await readOwnerRecord(lockPath);
|
|
4109
|
+
return record2.state === "record" ? record2.owner : null;
|
|
3792
4110
|
}
|
|
3793
4111
|
function processExists(pid) {
|
|
3794
4112
|
try {
|
|
@@ -3983,12 +4301,12 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
|
|
|
3983
4301
|
}
|
|
3984
4302
|
async function rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy) {
|
|
3985
4303
|
const started = Date.now();
|
|
3986
|
-
const
|
|
3987
|
-
if (
|
|
3988
|
-
if (
|
|
4304
|
+
const record2 = await resolveOwnerRecord(lockPath, started, waitMs, pollMs);
|
|
4305
|
+
if (record2.state === "record") {
|
|
4306
|
+
if (record2.owner.token === owner.token) await removeReleasedLock(lockPath, owner, started, waitMs, pollMs, policy);
|
|
3989
4307
|
return;
|
|
3990
4308
|
}
|
|
3991
|
-
if (
|
|
4309
|
+
if (record2.state === "unreadable" || !await isClaimedDirectory(lockPath, claimed)) return;
|
|
3992
4310
|
const remnant = releasedLockRemnantPath(lockPath, owner);
|
|
3993
4311
|
await fs.rename(lockPath, remnant);
|
|
3994
4312
|
await fs.rm(remnant, { recursive: true, force: true });
|
|
@@ -4151,12 +4469,62 @@ async function existingAnchor(resolved) {
|
|
|
4151
4469
|
candidate = parent;
|
|
4152
4470
|
}
|
|
4153
4471
|
}
|
|
4154
|
-
async function
|
|
4155
|
-
const foldedRel = relSegments(rel).map(foldSegment).join("/");
|
|
4472
|
+
async function foldedPhysicalRoot(root) {
|
|
4156
4473
|
const { anchor, tail } = await existingAnchor(path2.resolve(root));
|
|
4157
4474
|
const anchorSegments = anchor.split(path2.sep).filter((segment, index) => index === 0 || segment !== "");
|
|
4158
|
-
|
|
4159
|
-
|
|
4475
|
+
return [...anchorSegments, ...tail].map(foldSegment).join("/");
|
|
4476
|
+
}
|
|
4477
|
+
async function identityKey(root, rel) {
|
|
4478
|
+
const foldedRel = relSegments(rel).map(foldSegment).join("/");
|
|
4479
|
+
return createHash2("sha256").update(`superbee-identity/v1\0${await foldedPhysicalRoot(root)}\0${foldedRel}`).digest("hex");
|
|
4480
|
+
}
|
|
4481
|
+
async function filesystemRootMutationKey(root) {
|
|
4482
|
+
return createHash2("sha256").update(`superbee-root-mutation/v1\0${await foldedPhysicalRoot(root)}`).digest("hex");
|
|
4483
|
+
}
|
|
4484
|
+
async function filesystemRootWitness(port, root) {
|
|
4485
|
+
const physical = await fs2.realpath(root);
|
|
4486
|
+
const witnesses = [];
|
|
4487
|
+
let current = physical;
|
|
4488
|
+
for (; ; ) {
|
|
4489
|
+
const witness = await port.probe(current);
|
|
4490
|
+
if (!witness || witness.kind !== "directory") throw new InvalidInputError("Inventory guard root identity is unavailable.");
|
|
4491
|
+
witnesses.push([current, witness.dev, witness.ino]);
|
|
4492
|
+
const parent = path2.dirname(current);
|
|
4493
|
+
if (parent === current) break;
|
|
4494
|
+
current = parent;
|
|
4495
|
+
}
|
|
4496
|
+
return createHash2("sha256").update(JSON.stringify(witnesses)).digest("hex");
|
|
4497
|
+
}
|
|
4498
|
+
var rootMutationQueues = /* @__PURE__ */ new Map();
|
|
4499
|
+
function createFilesystemMutationCoordinator(_port, root, hostPolicy) {
|
|
4500
|
+
const policy = captureFilesystemHostPolicy(hostPolicy);
|
|
4501
|
+
let lockRoot;
|
|
4502
|
+
const namespace = () => lockRoot ??= filesystemMutationLockRoot(root, policy);
|
|
4503
|
+
return Object.freeze({
|
|
4504
|
+
namespace,
|
|
4505
|
+
async run(body) {
|
|
4506
|
+
const key = await filesystemRootMutationKey(root);
|
|
4507
|
+
const lockRoot2 = namespace();
|
|
4508
|
+
const queueKey = `${lockRoot2}:${key}`;
|
|
4509
|
+
const previous = rootMutationQueues.get(queueKey) ?? Promise.resolve();
|
|
4510
|
+
const run = previous.then(async () => {
|
|
4511
|
+
const release = await acquireFilesystemIdentityLock(key, root, { portableRoot: root, lockRoot: lockRoot2, hostPolicy: policy });
|
|
4512
|
+
try {
|
|
4513
|
+
return await body();
|
|
4514
|
+
} finally {
|
|
4515
|
+
await release();
|
|
4516
|
+
}
|
|
4517
|
+
});
|
|
4518
|
+
const settled = run.then(() => {
|
|
4519
|
+
}, () => {
|
|
4520
|
+
});
|
|
4521
|
+
rootMutationQueues.set(queueKey, settled);
|
|
4522
|
+
void settled.then(() => {
|
|
4523
|
+
if (rootMutationQueues.get(queueKey) === settled) rootMutationQueues.delete(queueKey);
|
|
4524
|
+
});
|
|
4525
|
+
return run;
|
|
4526
|
+
}
|
|
4527
|
+
});
|
|
4160
4528
|
}
|
|
4161
4529
|
function sameWitness(a, b) {
|
|
4162
4530
|
return a.dev === b.dev && a.ino === b.ino;
|
|
@@ -4690,181 +5058,6 @@ function createNodeFilesystemIdentityPort(hostPolicy) {
|
|
|
4690
5058
|
});
|
|
4691
5059
|
}
|
|
4692
5060
|
|
|
4693
|
-
// ../core/src/sha256.ts
|
|
4694
|
-
var K = new Uint32Array([
|
|
4695
|
-
1116352408,
|
|
4696
|
-
1899447441,
|
|
4697
|
-
3049323471,
|
|
4698
|
-
3921009573,
|
|
4699
|
-
961987163,
|
|
4700
|
-
1508970993,
|
|
4701
|
-
2453635748,
|
|
4702
|
-
2870763221,
|
|
4703
|
-
3624381080,
|
|
4704
|
-
310598401,
|
|
4705
|
-
607225278,
|
|
4706
|
-
1426881987,
|
|
4707
|
-
1925078388,
|
|
4708
|
-
2162078206,
|
|
4709
|
-
2614888103,
|
|
4710
|
-
3248222580,
|
|
4711
|
-
3835390401,
|
|
4712
|
-
4022224774,
|
|
4713
|
-
264347078,
|
|
4714
|
-
604807628,
|
|
4715
|
-
770255983,
|
|
4716
|
-
1249150122,
|
|
4717
|
-
1555081692,
|
|
4718
|
-
1996064986,
|
|
4719
|
-
2554220882,
|
|
4720
|
-
2821834349,
|
|
4721
|
-
2952996808,
|
|
4722
|
-
3210313671,
|
|
4723
|
-
3336571891,
|
|
4724
|
-
3584528711,
|
|
4725
|
-
113926993,
|
|
4726
|
-
338241895,
|
|
4727
|
-
666307205,
|
|
4728
|
-
773529912,
|
|
4729
|
-
1294757372,
|
|
4730
|
-
1396182291,
|
|
4731
|
-
1695183700,
|
|
4732
|
-
1986661051,
|
|
4733
|
-
2177026350,
|
|
4734
|
-
2456956037,
|
|
4735
|
-
2730485921,
|
|
4736
|
-
2820302411,
|
|
4737
|
-
3259730800,
|
|
4738
|
-
3345764771,
|
|
4739
|
-
3516065817,
|
|
4740
|
-
3600352804,
|
|
4741
|
-
4094571909,
|
|
4742
|
-
275423344,
|
|
4743
|
-
430227734,
|
|
4744
|
-
506948616,
|
|
4745
|
-
659060556,
|
|
4746
|
-
883997877,
|
|
4747
|
-
958139571,
|
|
4748
|
-
1322822218,
|
|
4749
|
-
1537002063,
|
|
4750
|
-
1747873779,
|
|
4751
|
-
1955562222,
|
|
4752
|
-
2024104815,
|
|
4753
|
-
2227730452,
|
|
4754
|
-
2361852424,
|
|
4755
|
-
2428436474,
|
|
4756
|
-
2756734187,
|
|
4757
|
-
3204031479,
|
|
4758
|
-
3329325298
|
|
4759
|
-
]);
|
|
4760
|
-
var INITIAL_STATE = new Uint32Array([
|
|
4761
|
-
1779033703,
|
|
4762
|
-
3144134277,
|
|
4763
|
-
1013904242,
|
|
4764
|
-
2773480762,
|
|
4765
|
-
1359893119,
|
|
4766
|
-
2600822924,
|
|
4767
|
-
528734635,
|
|
4768
|
-
1541459225
|
|
4769
|
-
]);
|
|
4770
|
-
var encoder = new TextEncoder();
|
|
4771
|
-
function rotr(value, bits) {
|
|
4772
|
-
return value >>> bits | value << 32 - bits;
|
|
4773
|
-
}
|
|
4774
|
-
function compress(h, w, view, offset) {
|
|
4775
|
-
for (let i = 0; i < 16; i++) {
|
|
4776
|
-
w[i] = view.getUint32(offset + i * 4);
|
|
4777
|
-
}
|
|
4778
|
-
for (let i = 16; i < 64; i++) {
|
|
4779
|
-
const w15 = w[i - 15];
|
|
4780
|
-
const w2 = w[i - 2];
|
|
4781
|
-
const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ w15 >>> 3;
|
|
4782
|
-
const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ w2 >>> 10;
|
|
4783
|
-
w[i] = w[i - 16] + s0 + w[i - 7] + s1 >>> 0;
|
|
4784
|
-
}
|
|
4785
|
-
let a = h[0];
|
|
4786
|
-
let b = h[1];
|
|
4787
|
-
let c = h[2];
|
|
4788
|
-
let d = h[3];
|
|
4789
|
-
let e = h[4];
|
|
4790
|
-
let f = h[5];
|
|
4791
|
-
let g = h[6];
|
|
4792
|
-
let hh = h[7];
|
|
4793
|
-
for (let i = 0; i < 64; i++) {
|
|
4794
|
-
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
4795
|
-
const ch = e & f ^ ~e & g;
|
|
4796
|
-
const t1 = hh + S1 + ch + K[i] + w[i] >>> 0;
|
|
4797
|
-
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
4798
|
-
const maj = a & b ^ a & c ^ b & c;
|
|
4799
|
-
const t2 = S0 + maj >>> 0;
|
|
4800
|
-
hh = g;
|
|
4801
|
-
g = f;
|
|
4802
|
-
f = e;
|
|
4803
|
-
e = d + t1 >>> 0;
|
|
4804
|
-
d = c;
|
|
4805
|
-
c = b;
|
|
4806
|
-
b = a;
|
|
4807
|
-
a = t1 + t2 >>> 0;
|
|
4808
|
-
}
|
|
4809
|
-
h[0] = h[0] + a >>> 0;
|
|
4810
|
-
h[1] = h[1] + b >>> 0;
|
|
4811
|
-
h[2] = h[2] + c >>> 0;
|
|
4812
|
-
h[3] = h[3] + d >>> 0;
|
|
4813
|
-
h[4] = h[4] + e >>> 0;
|
|
4814
|
-
h[5] = h[5] + f >>> 0;
|
|
4815
|
-
h[6] = h[6] + g >>> 0;
|
|
4816
|
-
h[7] = h[7] + hh >>> 0;
|
|
4817
|
-
}
|
|
4818
|
-
function sha256HexOfBytes(bytes) {
|
|
4819
|
-
const h = new Uint32Array(INITIAL_STATE);
|
|
4820
|
-
const w = new Uint32Array(64);
|
|
4821
|
-
const length = bytes.byteLength;
|
|
4822
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, length);
|
|
4823
|
-
const fullBlocks = length >>> 6;
|
|
4824
|
-
for (let block = 0; block < fullBlocks; block++) {
|
|
4825
|
-
compress(h, w, view, block * 64);
|
|
4826
|
-
}
|
|
4827
|
-
const remaining = length - fullBlocks * 64;
|
|
4828
|
-
const tail = new Uint8Array(remaining + 1 + 8 > 64 ? 128 : 64);
|
|
4829
|
-
tail.set(bytes.subarray(fullBlocks * 64));
|
|
4830
|
-
tail[remaining] = 128;
|
|
4831
|
-
const tailView = new DataView(tail.buffer);
|
|
4832
|
-
const bitLengthHigh = Math.floor(length / 536870912);
|
|
4833
|
-
const bitLengthLow = length << 3 >>> 0;
|
|
4834
|
-
tailView.setUint32(tail.length - 8, bitLengthHigh);
|
|
4835
|
-
tailView.setUint32(tail.length - 4, bitLengthLow);
|
|
4836
|
-
for (let offset = 0; offset < tail.length; offset += 64) {
|
|
4837
|
-
compress(h, w, tailView, offset);
|
|
4838
|
-
}
|
|
4839
|
-
let hex = "";
|
|
4840
|
-
for (let i = 0; i < 8; i++) {
|
|
4841
|
-
hex += h[i].toString(16).padStart(8, "0");
|
|
4842
|
-
}
|
|
4843
|
-
return hex;
|
|
4844
|
-
}
|
|
4845
|
-
function sha256HexOfUtf8(input) {
|
|
4846
|
-
return sha256HexOfBytes(encoder.encode(input));
|
|
4847
|
-
}
|
|
4848
|
-
|
|
4849
|
-
// ../core/src/version-transport.ts
|
|
4850
|
-
function isContentVersion(value) {
|
|
4851
|
-
return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
4852
|
-
}
|
|
4853
|
-
var VersionConflict = class extends Error {
|
|
4854
|
-
name = "VersionConflict";
|
|
4855
|
-
id;
|
|
4856
|
-
expected;
|
|
4857
|
-
actual;
|
|
4858
|
-
constructor(id, expected, actual) {
|
|
4859
|
-
super(
|
|
4860
|
-
`version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
|
|
4861
|
-
);
|
|
4862
|
-
this.id = id;
|
|
4863
|
-
this.expected = expected;
|
|
4864
|
-
this.actual = actual;
|
|
4865
|
-
}
|
|
4866
|
-
};
|
|
4867
|
-
|
|
4868
5061
|
// ../core/src/versioning.ts
|
|
4869
5062
|
function sha256Hex(input) {
|
|
4870
5063
|
return sha256HexOfUtf8(input);
|
|
@@ -4924,6 +5117,66 @@ function reservedPath(dir, name) {
|
|
|
4924
5117
|
var FilesystemBackend = class _FilesystemBackend {
|
|
4925
5118
|
#root;
|
|
4926
5119
|
#port;
|
|
5120
|
+
#coordinator;
|
|
5121
|
+
/** The coordinator is private: no transaction callback or held-root capability escapes. */
|
|
5122
|
+
#withRootMutation(body) {
|
|
5123
|
+
return this.#coordinator.run(body);
|
|
5124
|
+
}
|
|
5125
|
+
#mutateExact(rel, body) {
|
|
5126
|
+
return this.#withRootMutation(() => mutateExact(this.#port, this.#root, rel, body));
|
|
5127
|
+
}
|
|
5128
|
+
#assertInventoryGuard() {
|
|
5129
|
+
if (Object.getPrototypeOf(this) !== _FilesystemBackend.prototype || ["read", "readMany", "list", "write", "delete", "writeReserved", "writeBlob", "deleteBlob", "readReserved"].some((name) => this[name] !== _FilesystemBackend.prototype[name])) {
|
|
5130
|
+
throw new InventoryGuardUnsupported("unqualified_filesystem_override");
|
|
5131
|
+
}
|
|
5132
|
+
}
|
|
5133
|
+
get inventoryGuard() {
|
|
5134
|
+
this.#assertInventoryGuard();
|
|
5135
|
+
return bindInventoryGuard(this, {
|
|
5136
|
+
observeTarget: () => this.#withRootMutation(() => {
|
|
5137
|
+
this.#assertInventoryGuard();
|
|
5138
|
+
return this.#guardTarget();
|
|
5139
|
+
}),
|
|
5140
|
+
compareInventoryAndWrite: async (input) => {
|
|
5141
|
+
const request = captureInventoryGuardRequest(input);
|
|
5142
|
+
const raw = stringifyDoc(request.doc.frontmatter, request.doc.body);
|
|
5143
|
+
return this.#withRootMutation(async () => {
|
|
5144
|
+
this.#assertInventoryGuard();
|
|
5145
|
+
const target = await this.#guardTarget();
|
|
5146
|
+
const inventory = [];
|
|
5147
|
+
const ids = await this.list();
|
|
5148
|
+
assertInventoryGuardBound(ids.length);
|
|
5149
|
+
const deadline = performance.now() + 5e3;
|
|
5150
|
+
for (const id of ids) {
|
|
5151
|
+
if (performance.now() > deadline) throw new InventoryGuardUnsupported("inventory_scan_time_bound");
|
|
5152
|
+
const raw2 = await readRawFilesystemDocument(this, id);
|
|
5153
|
+
parseMarkdown(new TextDecoder("utf-8", { fatal: true }).decode(raw2.bytes), pathFromConceptId(id), { okfVersion: target.edition });
|
|
5154
|
+
inventory.push({ id, version: raw2.version });
|
|
5155
|
+
}
|
|
5156
|
+
if (performance.now() > deadline) throw new InventoryGuardUnsupported("inventory_scan_time_bound");
|
|
5157
|
+
compareInventoryPremises(request, target, inventory);
|
|
5158
|
+
const version2 = await mutateExact(this.#port, this.#root, pathFromConceptId(request.id), async (leaf) => {
|
|
5159
|
+
compareInventoryPremises(request, await this.#guardTarget(), inventory);
|
|
5160
|
+
const bytes = await leaf.current();
|
|
5161
|
+
if (bytes === null || versionOfBytes(bytes.toString("utf8")) !== request.expectedVersion) throw new InventoryGuardConflict("target_version");
|
|
5162
|
+
await leaf.replace(Buffer.from(raw, "utf8"));
|
|
5163
|
+
return versionOfBytes(raw);
|
|
5164
|
+
});
|
|
5165
|
+
return { version: version2, target, inventory_digest: inventoryDigest(inventory) };
|
|
5166
|
+
});
|
|
5167
|
+
}
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
async #guardTarget() {
|
|
5171
|
+
const witness = await filesystemRootWitness(this.#port, this.#root);
|
|
5172
|
+
const metadata = await readRawFilesystemReserved(this, "", "index.md");
|
|
5173
|
+
const content = metadata === null ? null : new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(metadata.bytes);
|
|
5174
|
+
const edition = guardEdition(content);
|
|
5175
|
+
const after = await filesystemRootWitness(this.#port, this.#root);
|
|
5176
|
+
if (witness !== after) throw new InventoryGuardConflict("identity");
|
|
5177
|
+
const store = versionOfBytes(`${await filesystemRootMutationKey(this.#root)}:${this.#coordinator.namespace()}:${witness}`);
|
|
5178
|
+
return { contract: "inventory-guard/v1", domain: INVENTORY_GUARD_DOMAIN, adapter: "filesystem", store, edition, root_version: blobVersion(metadata.bytes) };
|
|
5179
|
+
}
|
|
4927
5180
|
/**
|
|
4928
5181
|
* The root is resolved once here: a relative root would otherwise re-resolve against the
|
|
4929
5182
|
* process's current directory on every operation, so a later `chdir` would silently move the
|
|
@@ -4932,6 +5185,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
4932
5185
|
constructor(root, options = {}) {
|
|
4933
5186
|
this.#port = createNodeFilesystemIdentityPort(options.hostPolicy);
|
|
4934
5187
|
this.#root = path3.resolve(root);
|
|
5188
|
+
this.#coordinator = createFilesystemMutationCoordinator(this.#port, this.#root, options.hostPolicy);
|
|
4935
5189
|
publicationContexts.set(this, { root: this.#root, port: this.#port });
|
|
4936
5190
|
}
|
|
4937
5191
|
async read(id) {
|
|
@@ -4976,7 +5230,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
4976
5230
|
assertSafeConceptId(id);
|
|
4977
5231
|
const raw = stringifyDoc(doc.frontmatter, doc.body ?? "");
|
|
4978
5232
|
const rel = pathFromConceptId(id);
|
|
4979
|
-
return mutateExact(
|
|
5233
|
+
return this.#mutateExact(rel, async (target) => {
|
|
4980
5234
|
if (options.expectedVersion !== void 0) {
|
|
4981
5235
|
const bytes = await target.current();
|
|
4982
5236
|
const current = bytes === null ? null : versionOfBytes(bytes.toString("utf8"));
|
|
@@ -4990,7 +5244,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
4990
5244
|
}
|
|
4991
5245
|
async delete(id, options = {}) {
|
|
4992
5246
|
assertSafeConceptId(id);
|
|
4993
|
-
return mutateExact(
|
|
5247
|
+
return this.#mutateExact(pathFromConceptId(id), async (target) => {
|
|
4994
5248
|
const bytes = await target.current();
|
|
4995
5249
|
if (bytes === null) return false;
|
|
4996
5250
|
const current = versionOfBytes(bytes.toString("utf8"));
|
|
@@ -5054,7 +5308,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5054
5308
|
assertSafeReservedDir(dir);
|
|
5055
5309
|
assertSafeReservedFilename(name);
|
|
5056
5310
|
const rel = reservedPath(dir, name);
|
|
5057
|
-
return mutateExact(
|
|
5311
|
+
return this.#mutateExact(rel, async (target) => {
|
|
5058
5312
|
if (options.expectedVersion !== void 0) {
|
|
5059
5313
|
const bytes = await target.current();
|
|
5060
5314
|
const current = bytes === null ? null : versionOfBytes(bytes.toString("utf8"));
|
|
@@ -5076,7 +5330,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5076
5330
|
}
|
|
5077
5331
|
async writeBlob(key, bytes, _contentType, options = {}) {
|
|
5078
5332
|
assertSafeBlobKey(key);
|
|
5079
|
-
return mutateExact(
|
|
5333
|
+
return this.#mutateExact(key, async (target) => {
|
|
5080
5334
|
if (options.expectedVersion !== void 0) {
|
|
5081
5335
|
const existing = await target.current();
|
|
5082
5336
|
const current = existing === null ? null : blobVersion(existing);
|
|
@@ -5090,7 +5344,7 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5090
5344
|
}
|
|
5091
5345
|
async deleteBlob(key, options = {}) {
|
|
5092
5346
|
assertSafeBlobKey(key);
|
|
5093
|
-
return mutateExact(
|
|
5347
|
+
return this.#mutateExact(key, async (target) => {
|
|
5094
5348
|
const existing = await target.current();
|
|
5095
5349
|
if (existing === null) return false;
|
|
5096
5350
|
const current = blobVersion(existing);
|
|
@@ -5108,8 +5362,8 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5108
5362
|
}
|
|
5109
5363
|
async listBlobs(prefix) {
|
|
5110
5364
|
const files = await walkFiles(this.#port, this.#root, (name) => !name.toLowerCase().endsWith(".md"));
|
|
5111
|
-
const
|
|
5112
|
-
const filtered = prefix ?
|
|
5365
|
+
const keys2 = files.map(toPosix);
|
|
5366
|
+
const filtered = prefix ? keys2.filter((k) => k.startsWith(prefix)) : keys2;
|
|
5113
5367
|
filtered.sort(compareStorageKeys);
|
|
5114
5368
|
return filtered;
|
|
5115
5369
|
}
|
|
@@ -5123,6 +5377,35 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5123
5377
|
};
|
|
5124
5378
|
}
|
|
5125
5379
|
};
|
|
5380
|
+
function publicationContext(backend) {
|
|
5381
|
+
const context = publicationContexts.get(backend);
|
|
5382
|
+
if (!context) throw new InvalidInputError("Unknown filesystem backend publication source.");
|
|
5383
|
+
return context;
|
|
5384
|
+
}
|
|
5385
|
+
async function readRawFilesystemDocument(backend, id) {
|
|
5386
|
+
return readRawDocumentIn(backend, id);
|
|
5387
|
+
}
|
|
5388
|
+
async function readRawDocumentIn(backend, id, pass) {
|
|
5389
|
+
assertSafeConceptId(id);
|
|
5390
|
+
const { root, port } = publicationContext(backend);
|
|
5391
|
+
const rel = pathFromConceptId(id);
|
|
5392
|
+
const read = (handle) => readBytes(port, handle);
|
|
5393
|
+
const observed = pass ? await pass.observe(rel, read) : await observeExact(port, root, rel, read);
|
|
5394
|
+
if (observed.state === "absent") throw notFound(root, rel);
|
|
5395
|
+
const raw = new TextDecoder("utf-8", { fatal: true }).decode(observed.value);
|
|
5396
|
+
return { bytes: observed.value.slice(), version: versionOfBytes(raw) };
|
|
5397
|
+
}
|
|
5398
|
+
async function readRawFilesystemReserved(backend, dir, name) {
|
|
5399
|
+
assertSafeReservedDir(dir);
|
|
5400
|
+
assertSafeReservedFilename(name);
|
|
5401
|
+
const { root, port } = publicationContext(backend);
|
|
5402
|
+
const observed = await observeExact(port, root, reservedPath(dir, name), (handle) => readBytes(port, handle));
|
|
5403
|
+
if (observed.state === "absent") return null;
|
|
5404
|
+
return {
|
|
5405
|
+
bytes: observed.value.slice(),
|
|
5406
|
+
version: versionOfBytes(observed.value.toString("utf8"))
|
|
5407
|
+
};
|
|
5408
|
+
}
|
|
5126
5409
|
|
|
5127
5410
|
// ../core/src/bundle-ops.ts
|
|
5128
5411
|
var defaultBackendFactory;
|
|
@@ -5157,6 +5440,86 @@ async function queryEdges2(bundle, filter = {}, options = {}) {
|
|
|
5157
5440
|
// ../core/src/bundle.ts
|
|
5158
5441
|
setDefaultBackendFactory((root) => new FilesystemBackend(root));
|
|
5159
5442
|
|
|
5443
|
+
// ../core/src/managed-document-metadata.ts
|
|
5444
|
+
var MANAGED_DOCUMENT_METADATA_FIELDS = /* @__PURE__ */ new Set([
|
|
5445
|
+
"generated",
|
|
5446
|
+
"verified",
|
|
5447
|
+
"superbee_updated_by",
|
|
5448
|
+
"actor",
|
|
5449
|
+
"timestamp"
|
|
5450
|
+
]);
|
|
5451
|
+
function isManagedDocumentMetadataField(field) {
|
|
5452
|
+
return MANAGED_DOCUMENT_METADATA_FIELDS.has(field);
|
|
5453
|
+
}
|
|
5454
|
+
|
|
5455
|
+
// ../core/src/kind-deprecation.ts
|
|
5456
|
+
var problem = (field, message) => ({
|
|
5457
|
+
code: "KIND_DEPRECATION_INVALID",
|
|
5458
|
+
field,
|
|
5459
|
+
message: `${field}: ${message}`,
|
|
5460
|
+
severity: "warning"
|
|
5461
|
+
});
|
|
5462
|
+
function parseKindDeprecation(raw, kind, reserved, claimFields) {
|
|
5463
|
+
const result = { fields: [], values: {}, links: [] };
|
|
5464
|
+
const problems = [];
|
|
5465
|
+
const fail2 = (field, message) => {
|
|
5466
|
+
problems.push(problem(field, message));
|
|
5467
|
+
};
|
|
5468
|
+
const names = (value, path4) => {
|
|
5469
|
+
if (!Array.isArray(value) || value.some((v) => typeof v !== "string" || !v.trim() || v !== v.trim())) {
|
|
5470
|
+
fail2(path4, "expected a list of nonempty exact names");
|
|
5471
|
+
return [];
|
|
5472
|
+
}
|
|
5473
|
+
return [...new Set(value)];
|
|
5474
|
+
};
|
|
5475
|
+
const protectedField = (field) => reserved.includes(field) || isOkfStandardField(field) || isManagedDocumentMetadataField(field) || claimFields.includes(field);
|
|
5476
|
+
if (!isOkfRecord(raw)) fail2("deprecated", "expected a map of fields, values and links");
|
|
5477
|
+
else {
|
|
5478
|
+
for (const key of Object.keys(raw)) if (!["fields", "values", "links"].includes(key)) fail2(`deprecated.${key}`, "unknown policy coordinate");
|
|
5479
|
+
if (Object.hasOwn(raw, "fields")) result.fields = names(raw.fields, "deprecated.fields");
|
|
5480
|
+
for (const field of result.fields) {
|
|
5481
|
+
if (!kind.fields.optional.includes(field) || kind.fields.required.includes(field) || protectedField(field)) {
|
|
5482
|
+
fail2(`deprecated.fields.${field}`, "only an optional, nonstandard, nonreserved, nonclaim field can be deprecated");
|
|
5483
|
+
}
|
|
5484
|
+
}
|
|
5485
|
+
if (Object.hasOwn(raw, "values")) {
|
|
5486
|
+
if (!isOkfRecord(raw.values)) fail2("deprecated.values", "expected a field-to-values map");
|
|
5487
|
+
else for (const [field, value] of Object.entries(raw.values)) {
|
|
5488
|
+
const path4 = `deprecated.values.${field}`;
|
|
5489
|
+
const values = Array.isArray(value) && value.every((v) => ["string", "number", "boolean"].includes(typeof v)) ? [...new Set(value.map(String))] : void 0;
|
|
5490
|
+
if (!values || values.some((v) => !v.trim())) {
|
|
5491
|
+
fail2(path4, "expected a list of enum members");
|
|
5492
|
+
continue;
|
|
5493
|
+
}
|
|
5494
|
+
Object.defineProperty(result.values, field, { value: values, enumerable: true, writable: true, configurable: true });
|
|
5495
|
+
const allowed = Object.hasOwn(kind.fields.values, field) ? kind.fields.values[field] : void 0;
|
|
5496
|
+
if (protectedField(field) || ![...kind.fields.required, ...kind.fields.optional].includes(field) || !allowed || values.some((v) => !allowed.includes(v)) || kind.fields.types?.[field] === "https-url-list") {
|
|
5497
|
+
fail2(path4, "expected members of a declared, nonstandard, nonclaim vocabulary");
|
|
5498
|
+
}
|
|
5499
|
+
const terminal = Object.hasOwn(kind.fields.terminal, field) ? kind.fields.terminal[field] : [];
|
|
5500
|
+
if (values.some((v) => terminal.includes(v))) fail2(path4, "terminal members require a separate migration");
|
|
5501
|
+
if (kind.fields.required.includes(field) && allowed && !allowed.some((v) => !values.includes(v))) fail2(path4, "a required field must retain an active member");
|
|
5502
|
+
}
|
|
5503
|
+
}
|
|
5504
|
+
if (Object.hasOwn(raw, "links")) result.links = names(raw.links, "deprecated.links");
|
|
5505
|
+
for (const label of result.links) if (!kind.links || !Object.hasOwn(kind.links, label)) fail2(`deprecated.links.${label}`, "expected an existing outbound label");
|
|
5506
|
+
}
|
|
5507
|
+
if (problems.length) {
|
|
5508
|
+
result.problems = problems;
|
|
5509
|
+
result.raw = structuredClone(raw);
|
|
5510
|
+
}
|
|
5511
|
+
return result;
|
|
5512
|
+
}
|
|
5513
|
+
function kindDeprecationProblems(kind, registry) {
|
|
5514
|
+
const problems = [...kind.deprecated?.problems ?? []];
|
|
5515
|
+
for (const label of kind.deprecated?.links ?? []) {
|
|
5516
|
+
if ([...registry?.kinds.values() ?? [kind]].some((k) => k.expectsInbound && Object.hasOwn(k.expectsInbound, label))) {
|
|
5517
|
+
problems.push(problem(`deprecated.links.${label}`, "the admitted registry still declares an inbound expectation for this label"));
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
return problems;
|
|
5521
|
+
}
|
|
5522
|
+
|
|
5160
5523
|
// ../core/src/kinds.ts
|
|
5161
5524
|
var CONVENTIONS_PREFIX = "conventions/";
|
|
5162
5525
|
var CONVENTION_TYPE = "Convention";
|
|
@@ -5220,6 +5583,7 @@ function buildKindRegistry(docs, initialWarnings = [], options = {}) {
|
|
|
5220
5583
|
}
|
|
5221
5584
|
accepted.set(kind.governs, kind);
|
|
5222
5585
|
}
|
|
5586
|
+
for (const kind of accepted.values()) warnings.push(...kindDeprecationProblems(kind, { kinds: accepted, warnings: [] }).filter((w) => !warnings.includes(w)));
|
|
5223
5587
|
const kinds = /* @__PURE__ */ new Map();
|
|
5224
5588
|
for (const kind of [...accepted.values()].sort(compareReadingOrder)) kinds.set(kind.governs, kind);
|
|
5225
5589
|
return { kinds, warnings };
|
|
@@ -5233,9 +5597,9 @@ function compareReadingOrder(a, b) {
|
|
|
5233
5597
|
var PROGRESS_STATUS_FIELD = "progress_status";
|
|
5234
5598
|
var SUPERBEE_PROGRESS_STATUS_FIELD = "superbee_progress_status";
|
|
5235
5599
|
function progressStatusStorageField(okfVersion) {
|
|
5236
|
-
const
|
|
5237
|
-
if (
|
|
5238
|
-
if (
|
|
5600
|
+
const version2 = okfVersion?.trim() || "0.1";
|
|
5601
|
+
if (version2 === "0.1") return "status";
|
|
5602
|
+
if (version2 === "0.2") return SUPERBEE_PROGRESS_STATUS_FIELD;
|
|
5239
5603
|
return void 0;
|
|
5240
5604
|
}
|
|
5241
5605
|
function declaresField(kind, field) {
|
|
@@ -5258,6 +5622,19 @@ function resolveKindFieldCoordinate(okfVersion, kind, field) {
|
|
|
5258
5622
|
if (field === PROGRESS_STATUS_FIELD && progress) return progress;
|
|
5259
5623
|
return void 0;
|
|
5260
5624
|
}
|
|
5625
|
+
function claimCoordinates(okfVersion, kind) {
|
|
5626
|
+
if (!kind.claim) return void 0;
|
|
5627
|
+
const resolve = (field) => field === void 0 ? void 0 : resolveKindFieldCoordinate(okfVersion, kind, field)?.storageField;
|
|
5628
|
+
const ownerField = resolve(kind.claim.ownerField);
|
|
5629
|
+
const stateField = resolve(kind.claim.stateField);
|
|
5630
|
+
const fields = [...new Set([ownerField, stateField].filter((f) => f !== void 0))];
|
|
5631
|
+
if (fields.length === 0) return void 0;
|
|
5632
|
+
return {
|
|
5633
|
+
...ownerField !== void 0 ? { ownerField } : {},
|
|
5634
|
+
...stateField !== void 0 ? { stateField } : {},
|
|
5635
|
+
fields
|
|
5636
|
+
};
|
|
5637
|
+
}
|
|
5261
5638
|
function readKindField(okfVersion, kind, frontmatter2, field) {
|
|
5262
5639
|
const coordinate = resolveKindFieldCoordinate(okfVersion, kind, field);
|
|
5263
5640
|
return coordinate ? frontmatter2[coordinate.storageField] : void 0;
|
|
@@ -5278,11 +5655,11 @@ function isPlainObject(value) {
|
|
|
5278
5655
|
const prototype = Object.getPrototypeOf(value);
|
|
5279
5656
|
return prototype === Object.prototype || prototype === null;
|
|
5280
5657
|
}
|
|
5281
|
-
function hasOwn(
|
|
5282
|
-
return Object.prototype.hasOwnProperty.call(
|
|
5658
|
+
function hasOwn(record2, key) {
|
|
5659
|
+
return Object.prototype.hasOwnProperty.call(record2, key);
|
|
5283
5660
|
}
|
|
5284
|
-
function setOwn(
|
|
5285
|
-
Object.defineProperty(
|
|
5661
|
+
function setOwn(record2, key, value) {
|
|
5662
|
+
Object.defineProperty(record2, key, { value, enumerable: true, configurable: true, writable: true });
|
|
5286
5663
|
}
|
|
5287
5664
|
function isScalar(value) {
|
|
5288
5665
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
@@ -5774,6 +6151,10 @@ function parseConventionDoc(doc, options = {}) {
|
|
|
5774
6151
|
if (browseCollapsed !== void 0) kind.browseCollapsed = browseCollapsed;
|
|
5775
6152
|
if (order !== void 0) kind.order = order;
|
|
5776
6153
|
if (claim !== void 0) kind.claim = claim;
|
|
6154
|
+
if (Object.hasOwn(fm, "deprecated")) {
|
|
6155
|
+
kind.deprecated = parseKindDeprecation(fm.deprecated, kind, RESERVED_KIND_FIELD_NAMES, claimCoordinates(options.okfVersion, kind)?.fields ?? []);
|
|
6156
|
+
warnings.push(...kind.deprecated.problems ?? []);
|
|
6157
|
+
}
|
|
5777
6158
|
return {
|
|
5778
6159
|
ok: true,
|
|
5779
6160
|
kind,
|
|
@@ -6303,8 +6684,8 @@ var BridgeService = class {
|
|
|
6303
6684
|
if (!after) return this.reload(launchId, "the View changed while its subscription was polled");
|
|
6304
6685
|
const changes = [];
|
|
6305
6686
|
const removed = [];
|
|
6306
|
-
for (const [id,
|
|
6307
|
-
if (subscription.baseline.get(id) !==
|
|
6687
|
+
for (const [id, version2] of next) {
|
|
6688
|
+
if (subscription.baseline.get(id) !== version2) changes.push({ id, version: version2 });
|
|
6308
6689
|
}
|
|
6309
6690
|
for (const id of subscription.baseline.keys()) {
|
|
6310
6691
|
if (!next.has(id)) removed.push(id);
|