@fedify/vocab-runtime 2.4.0-pr.936.41 → 2.4.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/deno.json +4 -2
- package/dist/{tests/docloader-Ck8bcBir.mjs → contexts-B09jb9Pi.cjs} +173 -274
- package/dist/{tests/docloader-S_gQZ2tt.cjs → contexts-DWrj4AGR.js} +169 -293
- package/dist/{docloader-C_dir7Xb.d.ts → docloader-BMHljyYb.d.cts} +68 -2
- package/dist/{docloader-D2DTRiyA.d.cts → docloader-BMHljyYb.d.ts} +68 -2
- package/dist/internal/jsonld-cache.cjs +70 -1
- package/dist/internal/jsonld-cache.d.cts +35 -2
- package/dist/internal/jsonld-cache.d.ts +35 -2
- package/dist/internal/jsonld-cache.js +67 -2
- package/dist/internal/portable-dereference.cjs +721 -0
- package/dist/internal/portable-dereference.d.cts +349 -0
- package/dist/internal/portable-dereference.d.ts +349 -0
- package/dist/internal/portable-dereference.js +702 -0
- package/dist/internal/signed-representation.cjs +378 -0
- package/dist/internal/signed-representation.d.cts +144 -0
- package/dist/internal/signed-representation.d.ts +144 -0
- package/dist/internal/signed-representation.js +371 -0
- package/dist/jsonld.cjs +2 -2
- package/dist/mod.cjs +762 -4529
- package/dist/mod.d.cts +427 -9
- package/dist/mod.d.ts +427 -10
- package/dist/mod.js +742 -4524
- package/dist/portable-6Aj-7dZJ.d.cts +160 -0
- package/dist/portable-nkTiqH0w.d.ts +160 -0
- package/dist/tests/body-DpC9p-iG.mjs +130 -0
- package/dist/tests/body-cKLBprYm.cjs +153 -0
- package/dist/tests/body.test.cjs +89 -0
- package/dist/tests/body.test.d.cts +1 -0
- package/dist/tests/body.test.d.mts +1 -0
- package/dist/tests/body.test.mjs +90 -0
- package/dist/tests/contexts-C9Lj11SC.cjs +4533 -0
- package/dist/tests/contexts-duRA_dDC.mjs +4522 -0
- package/dist/tests/decimal.test.cjs +9 -7
- package/dist/tests/decimal.test.mjs +9 -6
- package/dist/tests/digest-3FeH2Y-Q.cjs +176 -0
- package/dist/tests/digest-COC7xDiQ.mjs +141 -0
- package/dist/tests/digest.test.cjs +102 -0
- package/dist/tests/digest.test.d.cts +1 -0
- package/dist/tests/digest.test.d.mts +1 -0
- package/dist/tests/digest.test.mjs +103 -0
- package/dist/tests/docloader-DyZ1JGIl.cjs +398 -0
- package/dist/tests/docloader-tUmMeXjU.mjs +375 -0
- package/dist/tests/docloader.test.cjs +816 -39
- package/dist/tests/docloader.test.mjs +810 -34
- package/dist/tests/internal/multicodec.test.cjs +2 -3
- package/dist/tests/internal/multicodec.test.mjs +2 -2
- package/dist/tests/internal/portable-dereference.test.cjs +172 -0
- package/dist/tests/internal/portable-dereference.test.d.cts +1 -0
- package/dist/tests/internal/portable-dereference.test.d.mts +1 -0
- package/dist/tests/internal/portable-dereference.test.mjs +173 -0
- package/dist/tests/jsonld-CmDhHNTx.cjs +12 -0
- package/dist/tests/jsonld-DweIJ07b.mjs +5 -0
- package/dist/tests/jsonld-cache-BEXiiM-V.cjs +386 -0
- package/dist/tests/jsonld-cache-DFnWsLuZ.mjs +339 -0
- package/dist/tests/jsonld-cache.test.cjs +102 -298
- package/dist/tests/jsonld-cache.test.mjs +95 -289
- package/dist/tests/{key-_wXwomh_.cjs → key-C-AYkdJJ.cjs} +11 -4
- package/dist/tests/{key-CDGDH_vC.mjs → key-C2Db_TAJ.mjs} +11 -3
- package/dist/tests/key.test.cjs +6 -5
- package/dist/tests/key.test.mjs +6 -4
- package/dist/tests/{langstr-Di5AvKpB.mjs → langstr-DYRmJqFn.mjs} +5 -2
- package/dist/tests/{langstr-CbAxaeEZ.cjs → langstr-_PqsL1ae.cjs} +5 -2
- package/dist/tests/langstr.test.cjs +11 -4
- package/dist/tests/langstr.test.mjs +9 -2
- package/dist/tests/langtag-CUppHs_s.mjs +45 -0
- package/dist/tests/langtag-Czjvxfzx.cjs +50 -0
- package/dist/tests/langtag.test.cjs +45 -0
- package/dist/tests/langtag.test.d.cts +1 -0
- package/dist/tests/langtag.test.d.mts +1 -0
- package/dist/tests/langtag.test.mjs +46 -0
- package/dist/tests/link.test.cjs +2 -3
- package/dist/tests/link.test.mjs +2 -2
- package/dist/tests/multibase/multibase.test.cjs +8 -9
- package/dist/tests/multibase/multibase.test.mjs +6 -6
- package/dist/tests/{multibase-Bz_UUDtL.cjs → multibase-B5Mea7Ip.cjs} +19 -2
- package/dist/tests/{multibase-B4bvakyA.mjs → multibase-BPnF_L4e.mjs} +12 -1
- package/dist/tests/portable-dereference-DmTYDy2p.mjs +250 -0
- package/dist/tests/portable-dereference-qTLMqe2_.cjs +279 -0
- package/dist/tests/portable-media-5p8azal0.cjs +153 -0
- package/dist/tests/portable-media-B_lt9MMA.mjs +148 -0
- package/dist/tests/portable-media.test.cjs +222 -0
- package/dist/tests/portable-media.test.d.cts +1 -0
- package/dist/tests/portable-media.test.d.mts +1 -0
- package/dist/tests/portable-media.test.mjs +223 -0
- package/dist/tests/portable-workers.test.cjs +36 -0
- package/dist/tests/portable-workers.test.d.cts +2 -0
- package/dist/tests/portable-workers.test.d.mts +2 -0
- package/dist/tests/portable-workers.test.mjs +35 -0
- package/dist/tests/{request-uk51rkhO.cjs → request-BgjA9wyl.cjs} +10 -4
- package/dist/tests/{request-C8CaGwtt.mjs → request-DodZNukP.mjs} +8 -2
- package/dist/tests/request.test.cjs +7 -4
- package/dist/tests/request.test.mjs +5 -2
- package/dist/tests/signed-representation.test.cjs +588 -0
- package/dist/tests/signed-representation.test.d.cts +1 -0
- package/dist/tests/signed-representation.test.d.mts +1 -0
- package/dist/tests/signed-representation.test.mjs +589 -0
- package/dist/tests/temporal.test.cjs +1 -2
- package/dist/tests/temporal.test.mjs +1 -1
- package/dist/tests/url-BNakuZ8k.cjs +998 -0
- package/dist/tests/url-DMxmp7ZG.mjs +859 -0
- package/dist/tests/url.test.cjs +489 -6
- package/dist/tests/url.test.mjs +489 -5
- package/dist/url-DrGTR8yv.cjs +993 -0
- package/dist/url-Dzyp-NsC.js +860 -0
- package/package.json +27 -4
- package/scripts/test-bun.mjs +17 -0
- package/src/body.test.ts +125 -0
- package/src/body.ts +152 -0
- package/src/contexts/cid-v1.json +114 -0
- package/src/contexts/fep-22cd.json +21 -0
- package/src/contexts/fep-6757.json +12 -0
- package/src/contexts/joinmastodon.json +1 -1
- package/src/contexts/miscellany.json +17 -0
- package/src/contexts.ts +47 -1
- package/src/digest.test.ts +220 -0
- package/src/digest.ts +229 -0
- package/src/docloader.test.ts +1066 -27
- package/src/docloader.ts +322 -105
- package/src/internal/jsonld-cache.ts +97 -1
- package/src/internal/portable-dereference.test.ts +254 -0
- package/src/internal/portable-dereference.ts +1000 -0
- package/src/internal/signed-representation.ts +565 -0
- package/src/jsonld-cache.test.ts +89 -0
- package/src/key.test.ts +9 -0
- package/src/key.ts +11 -1
- package/src/langstr.test.ts +18 -1
- package/src/langstr.ts +6 -2
- package/src/langtag.test.ts +53 -0
- package/src/langtag.ts +76 -0
- package/src/mod.ts +29 -0
- package/src/multibase/multibase.test.ts +5 -5
- package/src/portable-media.test.ts +293 -0
- package/src/portable-media.ts +264 -0
- package/src/portable-workers.test.ts +81 -0
- package/src/portable.ts +180 -0
- package/src/preprocessor.ts +7 -0
- package/src/request.test.ts +10 -1
- package/src/request.ts +9 -1
- package/src/signed-representation.test.ts +338 -0
- package/src/url.test.ts +823 -3
- package/src/url.ts +700 -23
- package/tsdown.config.ts +2 -0
- package/dist/tests/url-CsOV_B_P.cjs +0 -482
- package/dist/tests/url-Du7RQQgP.mjs +0 -392
- package/dist/url-DD4F0ULf.cjs +0 -483
- package/dist/url-DGVbSVVi.js +0 -393
- /package/dist/{chunk-M78iaK0I.cjs → rolldown-runtime-B7lfambq.cjs} +0 -0
- /package/dist/tests/{link-NUUWCdnK.mjs → link-Cevmc87v.mjs} +0 -0
- /package/dist/tests/{link-FguCydMA.cjs → link-DlKm8bEr.cjs} +0 -0
- /package/dist/tests/{multicodec-CxGVGa91.cjs → multicodec-CLRPeW4N.cjs} +0 -0
- /package/dist/tests/{multicodec-CyFp54fI.mjs → multicodec-CRIj_05H.mjs} +0 -0
- /package/dist/tests/{chunk-C2EiDwsr.cjs → rolldown-runtime-emK7D4bc.cjs} +0 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_contexts = require("../contexts-B09jb9Pi.cjs");
|
|
4
|
+
//#region src/internal/signed-representation.ts
|
|
5
|
+
const RETAINED_SIGNED_REPRESENTATION = Symbol.for("@fedify/vocab-runtime.signedRepresentation.v1");
|
|
6
|
+
const SIGNED_VALUE_SCOPE = Symbol.for("@fedify/vocab-runtime.signedValueScope.v1");
|
|
7
|
+
/**
|
|
8
|
+
* The IRI namespace of the placeholder node references that stand in for a
|
|
9
|
+
* retained signed representation until the owning `toJsonLd()` frame puts the
|
|
10
|
+
* representation back.
|
|
11
|
+
*/
|
|
12
|
+
const MARKER_NAMESPACE = "urn:x-fedify-signed-value:";
|
|
13
|
+
/** Bounds applied when validating a retained signed representation. */
|
|
14
|
+
const MAX_VALIDATION_DEPTH = 64;
|
|
15
|
+
const MAX_VALIDATION_NODES = 1e5;
|
|
16
|
+
/**
|
|
17
|
+
* The depth to which placeholders are put back. It has to exceed
|
|
18
|
+
* {@link MAX_VALIDATION_DEPTH}, because a restored document is itself nested
|
|
19
|
+
* inside the document that embeds it. Running out of depth is an error
|
|
20
|
+
* rather than a stopping point: a placeholder left in an unvisited subtree
|
|
21
|
+
* would reach the wire in place of the secured child.
|
|
22
|
+
*/
|
|
23
|
+
const MAX_RESTORATION_DEPTH = 256;
|
|
24
|
+
/**
|
|
25
|
+
* JSON-LD keywords that may appear at the top level of a context definition
|
|
26
|
+
* without endangering placeholder recovery. `@vocab` and `@base` are checked
|
|
27
|
+
* separately because they can rewrite the placeholder IRI.
|
|
28
|
+
*/
|
|
29
|
+
const HARMLESS_CONTEXT_KEYWORDS = /* @__PURE__ */ new Set([
|
|
30
|
+
"@protected",
|
|
31
|
+
"@version",
|
|
32
|
+
"@propagate"
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* Keyword aliases that are safe to leave in place because the placeholder
|
|
36
|
+
* recovery walker understands them.
|
|
37
|
+
*/
|
|
38
|
+
const ALLOWED_KEYWORD_ALIASES = /* @__PURE__ */ new Map([["id", "@id"], ["type", "@type"]]);
|
|
39
|
+
function isJsonMap(value) {
|
|
40
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
41
|
+
const prototype = Object.getPrototypeOf(value);
|
|
42
|
+
return prototype === Object.prototype || prototype === null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Checks that a value is a plain JSON tree that is safe to embed verbatim in
|
|
46
|
+
* a serialized document: plain object and array prototypes only, string keys
|
|
47
|
+
* only, own enumerable data properties only, finite numbers, and no
|
|
48
|
+
* `undefined`.
|
|
49
|
+
*
|
|
50
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
51
|
+
* part of the public API contract. This is not considered public API for
|
|
52
|
+
* Semantic Versioning decisions.
|
|
53
|
+
*/
|
|
54
|
+
function isPlainJsonTree(value) {
|
|
55
|
+
let nodes = 0;
|
|
56
|
+
return check(value, 0);
|
|
57
|
+
function check(current, depth) {
|
|
58
|
+
if (depth > MAX_VALIDATION_DEPTH) return false;
|
|
59
|
+
if (++nodes > MAX_VALIDATION_NODES) return false;
|
|
60
|
+
if (current === null) return true;
|
|
61
|
+
switch (typeof current) {
|
|
62
|
+
case "string":
|
|
63
|
+
case "boolean": return true;
|
|
64
|
+
case "number": return Number.isFinite(current);
|
|
65
|
+
case "object": break;
|
|
66
|
+
default: return false;
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(current)) {
|
|
69
|
+
if (Object.getPrototypeOf(current) !== Array.prototype) return false;
|
|
70
|
+
if (Object.getOwnPropertySymbols(current).length > 0) return false;
|
|
71
|
+
for (let i = 0; i < current.length; i++) {
|
|
72
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, i);
|
|
73
|
+
if (descriptor == null || !("value" in descriptor)) return false;
|
|
74
|
+
if (!check(descriptor.value, depth + 1)) return false;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (!isJsonMap(current)) return false;
|
|
79
|
+
if (Object.getOwnPropertySymbols(current).length > 0) return false;
|
|
80
|
+
for (const key of Object.getOwnPropertyNames(current)) {
|
|
81
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
82
|
+
if (descriptor == null || !("value" in descriptor)) return false;
|
|
83
|
+
if (!descriptor.enumerable) return false;
|
|
84
|
+
if (!check(descriptor.value, depth + 1)) return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function deepFreeze(value) {
|
|
90
|
+
if (value == null || typeof value !== "object") return value;
|
|
91
|
+
if (Object.isFrozen(value)) return value;
|
|
92
|
+
Object.freeze(value);
|
|
93
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Attaches the secured JSON document that a signer captured for `target`.
|
|
98
|
+
*
|
|
99
|
+
* The document is the exact JSON value that the object's own Object Integrity
|
|
100
|
+
* Proof covers. Nested serialization embeds it verbatim instead of
|
|
101
|
+
* reconstructing the object under the parent's JSON-LD context. The value is
|
|
102
|
+
* deep-frozen, so it is independent of anything done to `target` afterwards.
|
|
103
|
+
*
|
|
104
|
+
* `clone()` never carries the attachment, because a clone is a fresh instance.
|
|
105
|
+
*
|
|
106
|
+
* @internal Technically exported for `@fedify/fedify` and generated
|
|
107
|
+
* vocabulary classes, but not part of the public API contract. This is not
|
|
108
|
+
* considered public API for Semantic Versioning decisions.
|
|
109
|
+
*/
|
|
110
|
+
function retainSignedRepresentation(target, securedDocument) {
|
|
111
|
+
if (!isJsonMap(securedDocument) || !isPlainJsonTree(securedDocument)) throw new TypeError(`The secured document must be a plain JSON map within the validation bounds (at most ${MAX_VALIDATION_DEPTH} levels deep and ${MAX_VALIDATION_NODES} nodes).`);
|
|
112
|
+
Object.defineProperty(target, RETAINED_SIGNED_REPRESENTATION, {
|
|
113
|
+
value: deepFreeze(securedDocument),
|
|
114
|
+
enumerable: false,
|
|
115
|
+
writable: false,
|
|
116
|
+
configurable: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns the secured JSON document retained for `target`, if any.
|
|
121
|
+
*
|
|
122
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
123
|
+
* part of the public API contract. This is not considered public API for
|
|
124
|
+
* Semantic Versioning decisions.
|
|
125
|
+
*/
|
|
126
|
+
function getRetainedSignedRepresentation(target) {
|
|
127
|
+
if (target == null || typeof target !== "object") return void 0;
|
|
128
|
+
const retained = target[RETAINED_SIGNED_REPRESENTATION];
|
|
129
|
+
return isJsonMap(retained) ? retained : void 0;
|
|
130
|
+
}
|
|
131
|
+
function resolveContextEntry(entry) {
|
|
132
|
+
if (typeof entry !== "string") return entry;
|
|
133
|
+
if (!Object.hasOwn(require_contexts.preloadedContexts, entry)) return void 0;
|
|
134
|
+
const document = require_contexts.preloadedContexts[entry];
|
|
135
|
+
if (!isJsonMap(document)) return void 0;
|
|
136
|
+
return document["@context"];
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Checks whether a JSON-LD context leaves placeholder node references
|
|
140
|
+
* recoverable after compaction.
|
|
141
|
+
*
|
|
142
|
+
* Placeholder recovery replaces a bare IRI string, `{"@id": …}`, or
|
|
143
|
+
* `{"id": …}`. A context that aliases `@id` under a different term, declares
|
|
144
|
+
* `@nest`, uses an `@id` or `@type` container, rebases or re-vocabularies the
|
|
145
|
+
* placeholder namespace, or defines a prefix that shortens the placeholder
|
|
146
|
+
* IRI could hide the placeholder from that walker or make the walker rewrite
|
|
147
|
+
* the wrong node. A context that cannot be resolved offline cannot be vetted
|
|
148
|
+
* at all. Any of those makes the context unsafe, and retention is then not
|
|
149
|
+
* used.
|
|
150
|
+
*
|
|
151
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
152
|
+
* part of the public API contract. This is not considered public API for
|
|
153
|
+
* Semantic Versioning decisions.
|
|
154
|
+
*/
|
|
155
|
+
function isMarkerSafeContext(context) {
|
|
156
|
+
return check(context, 0);
|
|
157
|
+
function check(current, depth) {
|
|
158
|
+
if (depth > 8) return false;
|
|
159
|
+
if (Array.isArray(current)) return current.every((entry) => check(entry, depth + 1));
|
|
160
|
+
if (typeof current === "string") {
|
|
161
|
+
const resolved = resolveContextEntry(current);
|
|
162
|
+
if (resolved === void 0) return false;
|
|
163
|
+
return check(resolved, depth + 1);
|
|
164
|
+
}
|
|
165
|
+
if (current == null) return true;
|
|
166
|
+
if (!isJsonMap(current)) return false;
|
|
167
|
+
for (const [term, definition] of Object.entries(current)) {
|
|
168
|
+
if (term === "@vocab" || term === "@base") {
|
|
169
|
+
if (typeof definition !== "string") return false;
|
|
170
|
+
if (sharesMarkerNamespace(definition)) return false;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (term.startsWith("@")) {
|
|
174
|
+
if (!HARMLESS_CONTEXT_KEYWORDS.has(term)) return false;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (MARKER_NAMESPACE.startsWith(`${term}:`)) return false;
|
|
178
|
+
if (!checkTerm(term, definition, depth)) return false;
|
|
179
|
+
}
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
function checkTerm(term, definition, depth) {
|
|
183
|
+
if (definition == null) return true;
|
|
184
|
+
if (typeof definition === "string") return checkTermTarget(term, definition);
|
|
185
|
+
if (!isJsonMap(definition)) return false;
|
|
186
|
+
const target = definition["@id"];
|
|
187
|
+
if (target != null) {
|
|
188
|
+
if (typeof target !== "string") return false;
|
|
189
|
+
if (!checkTermTarget(term, target)) return false;
|
|
190
|
+
}
|
|
191
|
+
if ("@nest" in definition) return false;
|
|
192
|
+
if ("@reverse" in definition) return false;
|
|
193
|
+
const container = definition["@container"];
|
|
194
|
+
const containers = Array.isArray(container) ? container : container == null ? [] : [container];
|
|
195
|
+
for (const entry of containers) if (entry === "@id" || entry === "@type") return false;
|
|
196
|
+
if ("@context" in definition) {
|
|
197
|
+
if (!check(definition["@context"], depth + 1)) return false;
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
function checkTermTarget(term, target) {
|
|
202
|
+
if (target.startsWith("@")) return ALLOWED_KEYWORD_ALIASES.get(term) === target;
|
|
203
|
+
if (!target.includes(":")) return false;
|
|
204
|
+
return !sharesMarkerNamespace(target);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Reports whether an IRI prefix could shorten, relativize or otherwise hide a
|
|
209
|
+
* placeholder IRI. Both directions matter: a prefix shorter than the
|
|
210
|
+
* namespace covers every marker, and a longer one covers the markers whose
|
|
211
|
+
* random suffix happens to start with it.
|
|
212
|
+
*/
|
|
213
|
+
function sharesMarkerNamespace(prefix) {
|
|
214
|
+
return MARKER_NAMESPACE.startsWith(prefix) || prefix.startsWith(MARKER_NAMESPACE);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Joins the signed-value scope of the enclosing `toJsonLd()` frame, or starts
|
|
218
|
+
* one when this frame is the outermost.
|
|
219
|
+
*
|
|
220
|
+
* `options` must already be the internal copy that the generated encoder
|
|
221
|
+
* makes, never the object a caller passed in: the scope is attached to it as
|
|
222
|
+
* an enumerable symbol-keyed property so that every `{...options}` spread in
|
|
223
|
+
* the generated code propagates it to nested and inherited frames.
|
|
224
|
+
*
|
|
225
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
226
|
+
* part of the public API contract. This is not considered public API for
|
|
227
|
+
* Semantic Versioning decisions.
|
|
228
|
+
*/
|
|
229
|
+
function enterSignedValueScope(options) {
|
|
230
|
+
const existing = options[SIGNED_VALUE_SCOPE];
|
|
231
|
+
if (existing != null) return {
|
|
232
|
+
scope: existing,
|
|
233
|
+
owner: false
|
|
234
|
+
};
|
|
235
|
+
const scope = {
|
|
236
|
+
enabled: options.format !== "expand" && (options.context == null || isMarkerSafeContext(options.context)),
|
|
237
|
+
markers: /* @__PURE__ */ new Map(),
|
|
238
|
+
documents: /* @__PURE__ */ new Map()
|
|
239
|
+
};
|
|
240
|
+
Object.defineProperty(options, SIGNED_VALUE_SCOPE, {
|
|
241
|
+
value: scope,
|
|
242
|
+
enumerable: true,
|
|
243
|
+
writable: false,
|
|
244
|
+
configurable: true
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
scope,
|
|
248
|
+
owner: true
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Emits a placeholder node reference for a value that carries a retained
|
|
253
|
+
* signed representation, or `undefined` when it does not carry one.
|
|
254
|
+
*
|
|
255
|
+
* Both encoder paths use placeholders, never the retained document itself:
|
|
256
|
+
* an ancestor frame may still expand or compact the value, which would
|
|
257
|
+
* destroy an embedded document but leaves a node reference recoverable.
|
|
258
|
+
*
|
|
259
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
260
|
+
* part of the public API contract. This is not considered public API for
|
|
261
|
+
* Semantic Versioning decisions.
|
|
262
|
+
*/
|
|
263
|
+
function retainedSignedValueRef(value, scope) {
|
|
264
|
+
if (!scope.enabled) return void 0;
|
|
265
|
+
if (value == null || typeof value !== "object") return void 0;
|
|
266
|
+
const retained = getRetainedSignedRepresentation(value);
|
|
267
|
+
if (retained == null) return void 0;
|
|
268
|
+
let marker = scope.markers.get(value);
|
|
269
|
+
if (marker == null) {
|
|
270
|
+
if (!isPlainJsonTree(retained)) return void 0;
|
|
271
|
+
marker = `${MARKER_NAMESPACE}${crypto.randomUUID()}`;
|
|
272
|
+
scope.markers.set(value, marker);
|
|
273
|
+
scope.documents.set(marker, retained);
|
|
274
|
+
}
|
|
275
|
+
return { "@id": marker };
|
|
276
|
+
}
|
|
277
|
+
function markerOf(value, scope) {
|
|
278
|
+
return typeof value === "string" && scope.documents.has(value) ? value : void 0;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Puts every retained signed representation back in place of its placeholder
|
|
282
|
+
* node reference.
|
|
283
|
+
*
|
|
284
|
+
* Only the frame that owns the scope calls this, and only after compaction
|
|
285
|
+
* and context embedding are complete.
|
|
286
|
+
*
|
|
287
|
+
* @throws {TypeError} If a retained document was not put back anywhere, or if
|
|
288
|
+
* any trace of a placeholder survives. Both mean the serialized
|
|
289
|
+
* document does not contain the secured child it was told to embed,
|
|
290
|
+
* and emitting it would produce a signed child that silently fails
|
|
291
|
+
* verification.
|
|
292
|
+
*
|
|
293
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
294
|
+
* part of the public API contract. This is not considered public API for
|
|
295
|
+
* Semantic Versioning decisions.
|
|
296
|
+
*/
|
|
297
|
+
function resolveSignedValues(document, scope) {
|
|
298
|
+
if (scope.documents.size < 1) return document;
|
|
299
|
+
const restored = /* @__PURE__ */ new Set();
|
|
300
|
+
const resolved = restore(document, 0);
|
|
301
|
+
for (const marker of scope.documents.keys()) {
|
|
302
|
+
if (restored.has(marker)) continue;
|
|
303
|
+
throw new TypeError(`Failed to preserve a signed child representation: the placeholder ${marker} is not in the serialized document.`);
|
|
304
|
+
}
|
|
305
|
+
const trace = findMarkerTrace(resolved, scope);
|
|
306
|
+
if (trace != null) throw new TypeError(`Failed to preserve a signed child representation: a trace of the placeholder ${trace} survived serialization.`);
|
|
307
|
+
return resolved;
|
|
308
|
+
function restore(value, depth) {
|
|
309
|
+
if (depth > MAX_RESTORATION_DEPTH) throw new TypeError(`Failed to preserve a signed child representation: the serialized document is nested deeper than ${MAX_RESTORATION_DEPTH} levels, so a placeholder could be left unresolved.`);
|
|
310
|
+
const direct = markerOf(value, scope);
|
|
311
|
+
if (direct != null) return take(direct);
|
|
312
|
+
if (Array.isArray(value)) {
|
|
313
|
+
let changed = false;
|
|
314
|
+
const mapped = value.map((item) => {
|
|
315
|
+
const next = restore(item, depth + 1);
|
|
316
|
+
if (next !== item) changed = true;
|
|
317
|
+
return next;
|
|
318
|
+
});
|
|
319
|
+
return changed ? mapped : value;
|
|
320
|
+
}
|
|
321
|
+
if (!isJsonMap(value)) return value;
|
|
322
|
+
const keys = Object.keys(value);
|
|
323
|
+
if (keys.length === 1 && (keys[0] === "@id" || keys[0] === "id")) {
|
|
324
|
+
const marker = markerOf(value[keys[0]], scope);
|
|
325
|
+
if (marker != null) return take(marker);
|
|
326
|
+
}
|
|
327
|
+
let changed = false;
|
|
328
|
+
const mapped = Object.create(null);
|
|
329
|
+
for (const key of keys) {
|
|
330
|
+
const next = key === "@context" ? value[key] : restore(value[key], depth + 1);
|
|
331
|
+
if (next !== value[key]) changed = true;
|
|
332
|
+
mapped[key] = next;
|
|
333
|
+
}
|
|
334
|
+
if (!changed) return value;
|
|
335
|
+
return Object.setPrototypeOf(mapped, Object.prototype);
|
|
336
|
+
}
|
|
337
|
+
function take(marker) {
|
|
338
|
+
restored.add(marker);
|
|
339
|
+
return structuredClone(scope.documents.get(marker));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Finds any surviving trace of a placeholder IRI in a resolved document,
|
|
344
|
+
* matching the random suffix rather than the whole IRI so that a shortened,
|
|
345
|
+
* relativized or otherwise rewritten marker is caught too.
|
|
346
|
+
*/
|
|
347
|
+
function findMarkerTrace(document, scope) {
|
|
348
|
+
const suffixes = /* @__PURE__ */ new Map();
|
|
349
|
+
for (const marker of scope.documents.keys()) suffixes.set(marker.slice(26), marker);
|
|
350
|
+
return search(document, 0);
|
|
351
|
+
function matched(value) {
|
|
352
|
+
for (const [suffix, marker] of suffixes) if (value.includes(suffix)) return marker;
|
|
353
|
+
}
|
|
354
|
+
function search(value, depth) {
|
|
355
|
+
if (depth > MAX_RESTORATION_DEPTH) throw new TypeError(`Failed to preserve a signed child representation: the serialized document is nested deeper than ${MAX_RESTORATION_DEPTH} levels, so a surviving placeholder could go unnoticed.`);
|
|
356
|
+
if (typeof value === "string") return matched(value);
|
|
357
|
+
if (Array.isArray(value)) {
|
|
358
|
+
for (const item of value) {
|
|
359
|
+
const found = search(item, depth + 1);
|
|
360
|
+
if (found != null) return found;
|
|
361
|
+
}
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (value == null || typeof value !== "object") return void 0;
|
|
365
|
+
for (const [key, child] of Object.entries(value)) {
|
|
366
|
+
const found = matched(key) ?? search(child, depth + 1);
|
|
367
|
+
if (found != null) return found;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//#endregion
|
|
372
|
+
exports.enterSignedValueScope = enterSignedValueScope;
|
|
373
|
+
exports.getRetainedSignedRepresentation = getRetainedSignedRepresentation;
|
|
374
|
+
exports.isMarkerSafeContext = isMarkerSafeContext;
|
|
375
|
+
exports.isPlainJsonTree = isPlainJsonTree;
|
|
376
|
+
exports.resolveSignedValues = resolveSignedValues;
|
|
377
|
+
exports.retainSignedRepresentation = retainSignedRepresentation;
|
|
378
|
+
exports.retainedSignedValueRef = retainedSignedValueRef;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
//#region src/internal/signed-representation.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* A JSON map. Retained signed representations are always plain JSON maps.
|
|
5
|
+
*
|
|
6
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
7
|
+
* part of the public API contract. This is not considered public API for
|
|
8
|
+
* Semantic Versioning decisions.
|
|
9
|
+
*/
|
|
10
|
+
type SignedRepresentationJsonMap = Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Checks that a value is a plain JSON tree that is safe to embed verbatim in
|
|
13
|
+
* a serialized document: plain object and array prototypes only, string keys
|
|
14
|
+
* only, own enumerable data properties only, finite numbers, and no
|
|
15
|
+
* `undefined`.
|
|
16
|
+
*
|
|
17
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
18
|
+
* part of the public API contract. This is not considered public API for
|
|
19
|
+
* Semantic Versioning decisions.
|
|
20
|
+
*/
|
|
21
|
+
declare function isPlainJsonTree(value: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Attaches the secured JSON document that a signer captured for `target`.
|
|
24
|
+
*
|
|
25
|
+
* The document is the exact JSON value that the object's own Object Integrity
|
|
26
|
+
* Proof covers. Nested serialization embeds it verbatim instead of
|
|
27
|
+
* reconstructing the object under the parent's JSON-LD context. The value is
|
|
28
|
+
* deep-frozen, so it is independent of anything done to `target` afterwards.
|
|
29
|
+
*
|
|
30
|
+
* `clone()` never carries the attachment, because a clone is a fresh instance.
|
|
31
|
+
*
|
|
32
|
+
* @internal Technically exported for `@fedify/fedify` and generated
|
|
33
|
+
* vocabulary classes, but not part of the public API contract. This is not
|
|
34
|
+
* considered public API for Semantic Versioning decisions.
|
|
35
|
+
*/
|
|
36
|
+
declare function retainSignedRepresentation(target: object, securedDocument: SignedRepresentationJsonMap): void;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the secured JSON document retained for `target`, if any.
|
|
39
|
+
*
|
|
40
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
41
|
+
* part of the public API contract. This is not considered public API for
|
|
42
|
+
* Semantic Versioning decisions.
|
|
43
|
+
*/
|
|
44
|
+
declare function getRetainedSignedRepresentation(target: unknown): SignedRepresentationJsonMap | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Checks whether a JSON-LD context leaves placeholder node references
|
|
47
|
+
* recoverable after compaction.
|
|
48
|
+
*
|
|
49
|
+
* Placeholder recovery replaces a bare IRI string, `{"@id": …}`, or
|
|
50
|
+
* `{"id": …}`. A context that aliases `@id` under a different term, declares
|
|
51
|
+
* `@nest`, uses an `@id` or `@type` container, rebases or re-vocabularies the
|
|
52
|
+
* placeholder namespace, or defines a prefix that shortens the placeholder
|
|
53
|
+
* IRI could hide the placeholder from that walker or make the walker rewrite
|
|
54
|
+
* the wrong node. A context that cannot be resolved offline cannot be vetted
|
|
55
|
+
* at all. Any of those makes the context unsafe, and retention is then not
|
|
56
|
+
* used.
|
|
57
|
+
*
|
|
58
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
59
|
+
* part of the public API contract. This is not considered public API for
|
|
60
|
+
* Semantic Versioning decisions.
|
|
61
|
+
*/
|
|
62
|
+
declare function isMarkerSafeContext(context: unknown): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* The per-`toJsonLd()`-call state that tracks retained children.
|
|
65
|
+
*
|
|
66
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
67
|
+
* part of the public API contract. This is not considered public API for
|
|
68
|
+
* Semantic Versioning decisions.
|
|
69
|
+
*/
|
|
70
|
+
interface SignedValueScope {
|
|
71
|
+
/** Whether retained representations may be embedded at all. */
|
|
72
|
+
readonly enabled: boolean;
|
|
73
|
+
/** Marker IRI for each retained instance seen in this call. */
|
|
74
|
+
readonly markers: Map<object, string>;
|
|
75
|
+
/** Retained document for each marker IRI. */
|
|
76
|
+
readonly documents: Map<string, SignedRepresentationJsonMap>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The result of entering a signed-value scope.
|
|
80
|
+
*
|
|
81
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
82
|
+
* part of the public API contract. This is not considered public API for
|
|
83
|
+
* Semantic Versioning decisions.
|
|
84
|
+
*/
|
|
85
|
+
interface SignedValueScopeEntry {
|
|
86
|
+
readonly scope: SignedValueScope;
|
|
87
|
+
/**
|
|
88
|
+
* Whether this frame created the scope, and therefore has to put the
|
|
89
|
+
* retained documents back before returning.
|
|
90
|
+
*/
|
|
91
|
+
readonly owner: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Joins the signed-value scope of the enclosing `toJsonLd()` frame, or starts
|
|
95
|
+
* one when this frame is the outermost.
|
|
96
|
+
*
|
|
97
|
+
* `options` must already be the internal copy that the generated encoder
|
|
98
|
+
* makes, never the object a caller passed in: the scope is attached to it as
|
|
99
|
+
* an enumerable symbol-keyed property so that every `{...options}` spread in
|
|
100
|
+
* the generated code propagates it to nested and inherited frames.
|
|
101
|
+
*
|
|
102
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
103
|
+
* part of the public API contract. This is not considered public API for
|
|
104
|
+
* Semantic Versioning decisions.
|
|
105
|
+
*/
|
|
106
|
+
declare function enterSignedValueScope(options: {
|
|
107
|
+
format?: "compact" | "expand";
|
|
108
|
+
context?: string | Record<string, string> | (string | Record<string, string>)[];
|
|
109
|
+
}): SignedValueScopeEntry;
|
|
110
|
+
/**
|
|
111
|
+
* Emits a placeholder node reference for a value that carries a retained
|
|
112
|
+
* signed representation, or `undefined` when it does not carry one.
|
|
113
|
+
*
|
|
114
|
+
* Both encoder paths use placeholders, never the retained document itself:
|
|
115
|
+
* an ancestor frame may still expand or compact the value, which would
|
|
116
|
+
* destroy an embedded document but leaves a node reference recoverable.
|
|
117
|
+
*
|
|
118
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
119
|
+
* part of the public API contract. This is not considered public API for
|
|
120
|
+
* Semantic Versioning decisions.
|
|
121
|
+
*/
|
|
122
|
+
declare function retainedSignedValueRef(value: unknown, scope: SignedValueScope): {
|
|
123
|
+
"@id": string;
|
|
124
|
+
} | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Puts every retained signed representation back in place of its placeholder
|
|
127
|
+
* node reference.
|
|
128
|
+
*
|
|
129
|
+
* Only the frame that owns the scope calls this, and only after compaction
|
|
130
|
+
* and context embedding are complete.
|
|
131
|
+
*
|
|
132
|
+
* @throws {TypeError} If a retained document was not put back anywhere, or if
|
|
133
|
+
* any trace of a placeholder survives. Both mean the serialized
|
|
134
|
+
* document does not contain the secured child it was told to embed,
|
|
135
|
+
* and emitting it would produce a signed child that silently fails
|
|
136
|
+
* verification.
|
|
137
|
+
*
|
|
138
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
139
|
+
* part of the public API contract. This is not considered public API for
|
|
140
|
+
* Semantic Versioning decisions.
|
|
141
|
+
*/
|
|
142
|
+
declare function resolveSignedValues(document: unknown, scope: SignedValueScope): unknown;
|
|
143
|
+
//#endregion
|
|
144
|
+
export { SignedRepresentationJsonMap, SignedValueScope, SignedValueScopeEntry, enterSignedValueScope, getRetainedSignedRepresentation, isMarkerSafeContext, isPlainJsonTree, resolveSignedValues, retainSignedRepresentation, retainedSignedValueRef };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
//#region src/internal/signed-representation.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* A JSON map. Retained signed representations are always plain JSON maps.
|
|
5
|
+
*
|
|
6
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
7
|
+
* part of the public API contract. This is not considered public API for
|
|
8
|
+
* Semantic Versioning decisions.
|
|
9
|
+
*/
|
|
10
|
+
type SignedRepresentationJsonMap = Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Checks that a value is a plain JSON tree that is safe to embed verbatim in
|
|
13
|
+
* a serialized document: plain object and array prototypes only, string keys
|
|
14
|
+
* only, own enumerable data properties only, finite numbers, and no
|
|
15
|
+
* `undefined`.
|
|
16
|
+
*
|
|
17
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
18
|
+
* part of the public API contract. This is not considered public API for
|
|
19
|
+
* Semantic Versioning decisions.
|
|
20
|
+
*/
|
|
21
|
+
declare function isPlainJsonTree(value: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Attaches the secured JSON document that a signer captured for `target`.
|
|
24
|
+
*
|
|
25
|
+
* The document is the exact JSON value that the object's own Object Integrity
|
|
26
|
+
* Proof covers. Nested serialization embeds it verbatim instead of
|
|
27
|
+
* reconstructing the object under the parent's JSON-LD context. The value is
|
|
28
|
+
* deep-frozen, so it is independent of anything done to `target` afterwards.
|
|
29
|
+
*
|
|
30
|
+
* `clone()` never carries the attachment, because a clone is a fresh instance.
|
|
31
|
+
*
|
|
32
|
+
* @internal Technically exported for `@fedify/fedify` and generated
|
|
33
|
+
* vocabulary classes, but not part of the public API contract. This is not
|
|
34
|
+
* considered public API for Semantic Versioning decisions.
|
|
35
|
+
*/
|
|
36
|
+
declare function retainSignedRepresentation(target: object, securedDocument: SignedRepresentationJsonMap): void;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the secured JSON document retained for `target`, if any.
|
|
39
|
+
*
|
|
40
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
41
|
+
* part of the public API contract. This is not considered public API for
|
|
42
|
+
* Semantic Versioning decisions.
|
|
43
|
+
*/
|
|
44
|
+
declare function getRetainedSignedRepresentation(target: unknown): SignedRepresentationJsonMap | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Checks whether a JSON-LD context leaves placeholder node references
|
|
47
|
+
* recoverable after compaction.
|
|
48
|
+
*
|
|
49
|
+
* Placeholder recovery replaces a bare IRI string, `{"@id": …}`, or
|
|
50
|
+
* `{"id": …}`. A context that aliases `@id` under a different term, declares
|
|
51
|
+
* `@nest`, uses an `@id` or `@type` container, rebases or re-vocabularies the
|
|
52
|
+
* placeholder namespace, or defines a prefix that shortens the placeholder
|
|
53
|
+
* IRI could hide the placeholder from that walker or make the walker rewrite
|
|
54
|
+
* the wrong node. A context that cannot be resolved offline cannot be vetted
|
|
55
|
+
* at all. Any of those makes the context unsafe, and retention is then not
|
|
56
|
+
* used.
|
|
57
|
+
*
|
|
58
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
59
|
+
* part of the public API contract. This is not considered public API for
|
|
60
|
+
* Semantic Versioning decisions.
|
|
61
|
+
*/
|
|
62
|
+
declare function isMarkerSafeContext(context: unknown): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* The per-`toJsonLd()`-call state that tracks retained children.
|
|
65
|
+
*
|
|
66
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
67
|
+
* part of the public API contract. This is not considered public API for
|
|
68
|
+
* Semantic Versioning decisions.
|
|
69
|
+
*/
|
|
70
|
+
interface SignedValueScope {
|
|
71
|
+
/** Whether retained representations may be embedded at all. */
|
|
72
|
+
readonly enabled: boolean;
|
|
73
|
+
/** Marker IRI for each retained instance seen in this call. */
|
|
74
|
+
readonly markers: Map<object, string>;
|
|
75
|
+
/** Retained document for each marker IRI. */
|
|
76
|
+
readonly documents: Map<string, SignedRepresentationJsonMap>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The result of entering a signed-value scope.
|
|
80
|
+
*
|
|
81
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
82
|
+
* part of the public API contract. This is not considered public API for
|
|
83
|
+
* Semantic Versioning decisions.
|
|
84
|
+
*/
|
|
85
|
+
interface SignedValueScopeEntry {
|
|
86
|
+
readonly scope: SignedValueScope;
|
|
87
|
+
/**
|
|
88
|
+
* Whether this frame created the scope, and therefore has to put the
|
|
89
|
+
* retained documents back before returning.
|
|
90
|
+
*/
|
|
91
|
+
readonly owner: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Joins the signed-value scope of the enclosing `toJsonLd()` frame, or starts
|
|
95
|
+
* one when this frame is the outermost.
|
|
96
|
+
*
|
|
97
|
+
* `options` must already be the internal copy that the generated encoder
|
|
98
|
+
* makes, never the object a caller passed in: the scope is attached to it as
|
|
99
|
+
* an enumerable symbol-keyed property so that every `{...options}` spread in
|
|
100
|
+
* the generated code propagates it to nested and inherited frames.
|
|
101
|
+
*
|
|
102
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
103
|
+
* part of the public API contract. This is not considered public API for
|
|
104
|
+
* Semantic Versioning decisions.
|
|
105
|
+
*/
|
|
106
|
+
declare function enterSignedValueScope(options: {
|
|
107
|
+
format?: "compact" | "expand";
|
|
108
|
+
context?: string | Record<string, string> | (string | Record<string, string>)[];
|
|
109
|
+
}): SignedValueScopeEntry;
|
|
110
|
+
/**
|
|
111
|
+
* Emits a placeholder node reference for a value that carries a retained
|
|
112
|
+
* signed representation, or `undefined` when it does not carry one.
|
|
113
|
+
*
|
|
114
|
+
* Both encoder paths use placeholders, never the retained document itself:
|
|
115
|
+
* an ancestor frame may still expand or compact the value, which would
|
|
116
|
+
* destroy an embedded document but leaves a node reference recoverable.
|
|
117
|
+
*
|
|
118
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
119
|
+
* part of the public API contract. This is not considered public API for
|
|
120
|
+
* Semantic Versioning decisions.
|
|
121
|
+
*/
|
|
122
|
+
declare function retainedSignedValueRef(value: unknown, scope: SignedValueScope): {
|
|
123
|
+
"@id": string;
|
|
124
|
+
} | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Puts every retained signed representation back in place of its placeholder
|
|
127
|
+
* node reference.
|
|
128
|
+
*
|
|
129
|
+
* Only the frame that owns the scope calls this, and only after compaction
|
|
130
|
+
* and context embedding are complete.
|
|
131
|
+
*
|
|
132
|
+
* @throws {TypeError} If a retained document was not put back anywhere, or if
|
|
133
|
+
* any trace of a placeholder survives. Both mean the serialized
|
|
134
|
+
* document does not contain the secured child it was told to embed,
|
|
135
|
+
* and emitting it would produce a signed child that silently fails
|
|
136
|
+
* verification.
|
|
137
|
+
*
|
|
138
|
+
* @internal Technically exported for generated vocabulary classes, but not
|
|
139
|
+
* part of the public API contract. This is not considered public API for
|
|
140
|
+
* Semantic Versioning decisions.
|
|
141
|
+
*/
|
|
142
|
+
declare function resolveSignedValues(document: unknown, scope: SignedValueScope): unknown;
|
|
143
|
+
//#endregion
|
|
144
|
+
export { SignedRepresentationJsonMap, SignedValueScope, SignedValueScopeEntry, enterSignedValueScope, getRetainedSignedRepresentation, isMarkerSafeContext, isPlainJsonTree, resolveSignedValues, retainSignedRepresentation, retainedSignedValueRef };
|