@embedpdf/engine-core 3.0.0-next.13 → 3.0.0-next.15
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/dist/AnnotationList-CkijRHet.d.cts +27163 -0
- package/dist/AnnotationList-CkijRHet.d.ts +27163 -0
- package/dist/Change-CKoxfTNY.js +889 -0
- package/dist/Change-CKoxfTNY.js.map +1 -0
- package/dist/Change-CjImsrN0.cjs +1020 -0
- package/dist/Change-CjImsrN0.cjs.map +1 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs +120 -0
- package/dist/DocumentRenderService-BfFdFSwI.cjs.map +1 -0
- package/dist/DocumentRenderService-DV3J9lMz.js +85 -0
- package/dist/DocumentRenderService-DV3J9lMz.js.map +1 -0
- package/dist/{DocumentSecurityService-_JRjqvoI.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
- package/dist/{DocumentSecurityService-ClTZc0zO.d.cts → DocumentSecurityService-e6vp2de8.d.cts} +100 -112
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs +53 -0
- package/dist/LocalDocumentHandle-D02FMm-Z.cjs.map +1 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js +30 -0
- package/dist/LocalDocumentHandle-DAPdaOt_.js.map +1 -0
- package/dist/LocalEngine-DFoBm4B3.d.cts +1565 -0
- package/dist/LocalEngine-DPriFujS.d.ts +1565 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs +17 -0
- package/dist/PageInsertBlankInput-CXHAM7l6.cjs.map +1 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js +12 -0
- package/dist/PageInsertBlankInput-DhVYVJ_S.js.map +1 -0
- package/dist/authority-B3BklsB4.js +2239 -0
- package/dist/authority-B3BklsB4.js.map +1 -0
- package/dist/authority-DLMNR7ff.cjs +2676 -0
- package/dist/authority-DLMNR7ff.cjs.map +1 -0
- package/dist/builders-CNj0POeY.js +161 -0
- package/dist/builders-CNj0POeY.js.map +1 -0
- package/dist/builders-Cgdp_YCn.cjs +184 -0
- package/dist/builders-Cgdp_YCn.cjs.map +1 -0
- package/dist/calibrate-7T3fnP8-.js +2404 -0
- package/dist/calibrate-7T3fnP8-.js.map +1 -0
- package/dist/calibrate-DJBXnhLE.cjs +2919 -0
- package/dist/calibrate-DJBXnhLE.cjs.map +1 -0
- package/dist/charmap-Cprti1ta.js +239 -0
- package/dist/charmap-Cprti1ta.js.map +1 -0
- package/dist/charmap-aYlefQP9.cjs +304 -0
- package/dist/charmap-aYlefQP9.cjs.map +1 -0
- package/dist/conformance.cjs +16753 -5247
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +928 -165
- package/dist/conformance.d.ts +928 -165
- package/dist/conformance.js +16731 -5268
- package/dist/conformance.js.map +1 -1
- package/dist/format-Bp3QFSH1.cjs +574 -0
- package/dist/format-Bp3QFSH1.cjs.map +1 -0
- package/dist/format-Dgg428Kb.js +461 -0
- package/dist/format-Dgg428Kb.js.map +1 -0
- package/dist/index.cjs +330 -103
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -5
- package/dist/pageRefs-B3ur7Ckm.cjs +51 -0
- package/dist/pageRefs-B3ur7Ckm.cjs.map +1 -0
- package/dist/pageRefs-DkbuxSCV.js +40 -0
- package/dist/pageRefs-DkbuxSCV.js.map +1 -0
- package/dist/public.cjs +57 -0
- package/dist/public.d.cts +5 -0
- package/dist/public.d.ts +5 -0
- package/dist/public.js +9 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs +3646 -0
- package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs.map +1 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js +3167 -0
- package/dist/resolveAnnotationDraft-CUpf0SMh.js.map +1 -0
- package/dist/{resolver-inAVzsWt.js → resolver-CzxmD9Ck.js} +294 -144
- package/dist/resolver-CzxmD9Ck.js.map +1 -0
- package/dist/{resolver-CYVNV4hn.cjs → resolver-D2OCtE8F.cjs} +347 -143
- package/dist/resolver-D2OCtE8F.cjs.map +1 -0
- package/dist/runtime-Cl0v56mm.d.ts +2032 -0
- package/dist/runtime-p1WDzDo4.d.cts +2032 -0
- package/dist/runtime.cjs +733 -284
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +5 -1348
- package/dist/runtime.d.ts +5 -1348
- package/dist/runtime.js +396 -179
- package/dist/runtime.js.map +1 -1
- package/dist/schema-C-gU4vj7.cjs +3034 -0
- package/dist/schema-C-gU4vj7.cjs.map +1 -0
- package/dist/schema-DzlUNk38.js +2081 -0
- package/dist/schema-DzlUNk38.js.map +1 -0
- package/dist/schemas-Berf1swF.cjs +2481 -0
- package/dist/schemas-Berf1swF.cjs.map +1 -0
- package/dist/schemas-D6xOGjqg.js +1654 -0
- package/dist/schemas-D6xOGjqg.js.map +1 -0
- package/dist/subtype-CG4WpIRj.js +129 -0
- package/dist/subtype-CG4WpIRj.js.map +1 -0
- package/dist/subtype-aDt5TFmK.cjs +158 -0
- package/dist/subtype-aDt5TFmK.cjs.map +1 -0
- package/dist/validation.cjs +578 -0
- package/dist/validation.cjs.map +1 -0
- package/dist/validation.d.cts +174 -0
- package/dist/validation.d.ts +174 -0
- package/dist/validation.js +571 -0
- package/dist/validation.js.map +1 -0
- package/dist/value-BFS1R8ek.cjs +435 -0
- package/dist/value-BFS1R8ek.cjs.map +1 -0
- package/dist/value-Dhc8eYcx.js +340 -0
- package/dist/value-Dhc8eYcx.js.map +1 -0
- package/dist/viewport-BJW13EGZ.js +540 -0
- package/dist/viewport-BJW13EGZ.js.map +1 -0
- package/dist/viewport-DlL5Bxbg.cjs +671 -0
- package/dist/viewport-DlL5Bxbg.cjs.map +1 -0
- package/dist/wire.cjs +1056 -379
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +15069 -725
- package/dist/wire.d.ts +15069 -725
- package/dist/wire.js +825 -239
- package/dist/wire.js.map +1 -1
- package/package.json +10 -1
- package/dist/AbortError-Cq2igpZ6.cjs +0 -38
- package/dist/AbortError-Cq2igpZ6.cjs.map +0 -1
- package/dist/AbortError-DHqPBnYc.js +0 -27
- package/dist/AbortError-DHqPBnYc.js.map +0 -1
- package/dist/AnnotationListSnapshot-D3mFut1e.d.cts +0 -6871
- package/dist/AnnotationListSnapshot-D3mFut1e.d.ts +0 -6871
- package/dist/Engine-Bx0NOfmd.d.cts +0 -1264
- package/dist/Engine-DxtpCYcP.d.ts +0 -1264
- package/dist/PageInsertBlankInput-CqXBmFhN.cjs +0 -449
- package/dist/PageInsertBlankInput-CqXBmFhN.cjs.map +0 -1
- package/dist/PageInsertBlankInput-cHq9-i-z.js +0 -378
- package/dist/PageInsertBlankInput-cHq9-i-z.js.map +0 -1
- package/dist/builders-Bqm8yTpi.cjs +0 -3564
- package/dist/builders-Bqm8yTpi.cjs.map +0 -1
- package/dist/builders-Dqo2X-dt.js +0 -3121
- package/dist/builders-Dqo2X-dt.js.map +0 -1
- package/dist/fold-2V29cxCV.cjs +0 -447
- package/dist/fold-2V29cxCV.cjs.map +0 -1
- package/dist/fold-CdEJTBTn.js +0 -334
- package/dist/fold-CdEJTBTn.js.map +0 -1
- package/dist/resolver-CYVNV4hn.cjs.map +0 -1
- package/dist/resolver-inAVzsWt.js.map +0 -1
- package/dist/schemas-BLARNCgx.js +0 -3113
- package/dist/schemas-BLARNCgx.js.map +0 -1
- package/dist/schemas-DIqFMmrC.cjs +0 -4468
- package/dist/schemas-DIqFMmrC.cjs.map +0 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//#region src/auth/scope/builders.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed capability constants for customer-side JWT minting.
|
|
4
|
+
*
|
|
5
|
+
* The shape mirrors the dotted capability name so it reads naturally:
|
|
6
|
+
* caps.doc.text.copy() // "doc.text.copy"
|
|
7
|
+
* caps.doc.download() // "doc.download"
|
|
8
|
+
* caps.doc.download.flattened() // "doc.download.flattened"
|
|
9
|
+
* caps.doc.print.high() // "doc.print.high"
|
|
10
|
+
*
|
|
11
|
+
* Each leaf is a function returning the literal string (as `const`) so
|
|
12
|
+
* TypeScript catches typos at the call site. Wrappers like `download`
|
|
13
|
+
* and `print` are `Object.assign`'d to be callable and carry child
|
|
14
|
+
* properties for the refinement capabilities.
|
|
15
|
+
*/
|
|
16
|
+
const caps = { doc: {
|
|
17
|
+
open: () => "doc.open",
|
|
18
|
+
render: () => "doc.render",
|
|
19
|
+
text: {
|
|
20
|
+
select: () => "doc.text.select",
|
|
21
|
+
copy: () => "doc.text.copy",
|
|
22
|
+
search: () => "doc.text.search"
|
|
23
|
+
},
|
|
24
|
+
content: { copy: () => "doc.content.copy" },
|
|
25
|
+
download: Object.assign(() => "doc.download", { flattened: () => "doc.download.flattened" }),
|
|
26
|
+
print: Object.assign(() => "doc.print", { high: () => "doc.print.high" }),
|
|
27
|
+
pages: {
|
|
28
|
+
modify: () => "doc.pages.modify",
|
|
29
|
+
assemble: () => "doc.pages.assemble"
|
|
30
|
+
},
|
|
31
|
+
forms: {
|
|
32
|
+
read: () => "doc.forms.read",
|
|
33
|
+
fill: () => "doc.forms.fill",
|
|
34
|
+
modify: () => "doc.forms.modify",
|
|
35
|
+
import: () => "doc.forms.import",
|
|
36
|
+
script: () => "doc.forms.script",
|
|
37
|
+
submit: () => "doc.forms.submit"
|
|
38
|
+
},
|
|
39
|
+
annotate: {
|
|
40
|
+
read: () => "doc.annotate.read",
|
|
41
|
+
modify: () => "doc.annotate.modify",
|
|
42
|
+
import: () => "doc.annotate.import"
|
|
43
|
+
},
|
|
44
|
+
metadata: { modify: () => "doc.metadata.modify" },
|
|
45
|
+
attachments: { modify: () => "doc.attachments.modify" },
|
|
46
|
+
redact: () => "doc.redact",
|
|
47
|
+
sign: Object.assign(() => "doc.sign", { certify: () => "doc.sign.certify" })
|
|
48
|
+
} };
|
|
49
|
+
/**
|
|
50
|
+
* Builder factory for collab scope filters. Each entity:action pair
|
|
51
|
+
* gets a sub-object with the four filter constructors.
|
|
52
|
+
*
|
|
53
|
+
* collab.annotations.create.self() → "annotations:create:self"
|
|
54
|
+
* collab.annotations.create.group("legal") → "annotations:create:group=legal"
|
|
55
|
+
* collab.annotations.update.group("4") → "annotations:update:group=4"
|
|
56
|
+
* collab.annotations.delete.createdBy("u-7") → "annotations:delete:createdBy=u-7"
|
|
57
|
+
* collab.annotations.setGroup.group("legal") → "annotations:set-group:group=legal"
|
|
58
|
+
* collab.annotations.all.all() → "annotations:*:all" (action wildcard)
|
|
59
|
+
* collab.fields.fill.group("buyer") → "fields:fill:group=buyer"
|
|
60
|
+
* collab.fields.sign.group("buyer") → "fields:sign:group=buyer"
|
|
61
|
+
* collab.fields.all.group("seller") → "fields:*:group=seller"
|
|
62
|
+
*
|
|
63
|
+
* On create, the filter is evaluated against the caller's own identity
|
|
64
|
+
* (no impersonation), so `:self` and `:all` trivially pass; `:group=X`
|
|
65
|
+
* is the meaningful filter — it constrains creation to callers whose
|
|
66
|
+
* default group is X.
|
|
67
|
+
*/
|
|
68
|
+
const collab = {
|
|
69
|
+
annotations: {
|
|
70
|
+
create: makeFilterBuilder("annotations", "create"),
|
|
71
|
+
update: makeFilterBuilder("annotations", "update"),
|
|
72
|
+
delete: makeFilterBuilder("annotations", "delete"),
|
|
73
|
+
setGroup: makeGroupFilterBuilder("annotations", "set-group"),
|
|
74
|
+
/** Action wildcard — matches create, update, delete, and set-group with the given filter. */
|
|
75
|
+
all: makeFilterBuilder("annotations", "*")
|
|
76
|
+
},
|
|
77
|
+
/** Form fields, by group: a field records no creator, so only `:all` and `:group=X`. */
|
|
78
|
+
fields: {
|
|
79
|
+
fill: makeGroupFilterBuilder("fields", "fill"),
|
|
80
|
+
sign: makeGroupFilterBuilder("fields", "sign"),
|
|
81
|
+
setGroup: makeGroupFilterBuilder("fields", "set-group"),
|
|
82
|
+
/** Action wildcard — matches fill, sign, and set-group with the given filter. */
|
|
83
|
+
all: makeGroupFilterBuilder("fields", "*")
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
function makeFilterBuilder(entity, action) {
|
|
87
|
+
return {
|
|
88
|
+
all: () => `${entity}:${action}:all`,
|
|
89
|
+
self: () => `${entity}:${action}:self`,
|
|
90
|
+
createdBy: (userId) => `${entity}:${action}:createdBy=${userId}`,
|
|
91
|
+
group: (groupId) => `${entity}:${action}:group=${groupId}`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function makeGroupFilterBuilder(entity, action) {
|
|
95
|
+
return {
|
|
96
|
+
all: () => `${entity}:${action}:all`,
|
|
97
|
+
group: (groupId) => `${entity}:${action}:group=${groupId}`
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Builder for the `pdf.permissions` virtual scope. Returns the literal
|
|
102
|
+
* string; provided as a helper for parity with caps/collab in JWT
|
|
103
|
+
* construction code.
|
|
104
|
+
*/
|
|
105
|
+
const pdfPermissions = () => "pdf.permissions";
|
|
106
|
+
/**
|
|
107
|
+
* Materialise `pdf.permissions` into the concrete capability list it
|
|
108
|
+
* would expand to under the given PDF bit configuration.
|
|
109
|
+
*
|
|
110
|
+
* Useful when the customer wants to start from PDF defaults and then
|
|
111
|
+
* subtract specific capabilities — easier to build the JWT scope array
|
|
112
|
+
* by filtering an explicit list than by composing virtual + denials.
|
|
113
|
+
*
|
|
114
|
+
* const defaults = materializePdfPermissions(pdfBits);
|
|
115
|
+
* const scope = [
|
|
116
|
+
* ...defaults.filter(s => s !== 'doc.text.copy'),
|
|
117
|
+
* 'doc.download',
|
|
118
|
+
* ];
|
|
119
|
+
*
|
|
120
|
+
* This is the one reading of the bits: the scope resolver and the
|
|
121
|
+
* permission advisory both use it. It follows what Acrobat allows on a
|
|
122
|
+
* file with these bits, which is broader than ISO 32000 in two places:
|
|
123
|
+
* bit 4 ("changing the document") also allows filling in and signing, and
|
|
124
|
+
* bit 5 ("copying text and graphics") governs taking the text out, not
|
|
125
|
+
* finding or selecting it: Acrobat finds and selects text in a file that
|
|
126
|
+
* forbids copying. A search's snippets reproduce the text, so they need
|
|
127
|
+
* `doc.text.copy`.
|
|
128
|
+
*/
|
|
129
|
+
function materializePdfPermissions(b) {
|
|
130
|
+
const out = /* @__PURE__ */ new Set();
|
|
131
|
+
out.add("doc.open");
|
|
132
|
+
out.add("doc.render");
|
|
133
|
+
out.add("doc.annotate.read");
|
|
134
|
+
out.add("doc.forms.read");
|
|
135
|
+
out.add("doc.text.search");
|
|
136
|
+
out.add("doc.text.select");
|
|
137
|
+
if (b.bit5) {
|
|
138
|
+
out.add("doc.text.copy");
|
|
139
|
+
out.add("doc.content.copy");
|
|
140
|
+
}
|
|
141
|
+
if (b.bit3) out.add("doc.print");
|
|
142
|
+
if (b.bit12 && b.bit3) out.add("doc.print.high");
|
|
143
|
+
if (b.bit4) {
|
|
144
|
+
out.add("doc.pages.modify");
|
|
145
|
+
out.add("doc.redact");
|
|
146
|
+
out.add("doc.metadata.modify");
|
|
147
|
+
out.add("doc.attachments.modify");
|
|
148
|
+
}
|
|
149
|
+
if (b.bit4 || b.bit11) out.add("doc.pages.assemble");
|
|
150
|
+
if (b.bit6) out.add("doc.annotate.modify");
|
|
151
|
+
if (b.bit4 || b.bit6 || b.bit9) {
|
|
152
|
+
out.add("doc.forms.fill");
|
|
153
|
+
out.add("doc.sign");
|
|
154
|
+
}
|
|
155
|
+
if (b.bit6 && b.bit4) out.add("doc.forms.modify");
|
|
156
|
+
return [...out];
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { pdfPermissions as i, collab as n, materializePdfPermissions as r, caps as t };
|
|
160
|
+
|
|
161
|
+
//# sourceMappingURL=builders-CNj0POeY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders-CNj0POeY.js","names":[],"sources":["../src/auth/scope/builders.ts"],"sourcesContent":["import type { DocCapability, PdfBits } from './types';\n\n/**\n * Typed capability constants for customer-side JWT minting.\n *\n * The shape mirrors the dotted capability name so it reads naturally:\n * caps.doc.text.copy() // \"doc.text.copy\"\n * caps.doc.download() // \"doc.download\"\n * caps.doc.download.flattened() // \"doc.download.flattened\"\n * caps.doc.print.high() // \"doc.print.high\"\n *\n * Each leaf is a function returning the literal string (as `const`) so\n * TypeScript catches typos at the call site. Wrappers like `download`\n * and `print` are `Object.assign`'d to be callable and carry child\n * properties for the refinement capabilities.\n */\nexport const caps = {\n doc: {\n open: () => 'doc.open' as const,\n render: () => 'doc.render' as const,\n text: {\n select: () => 'doc.text.select' as const,\n copy: () => 'doc.text.copy' as const,\n search: () => 'doc.text.search' as const,\n },\n content: {\n copy: () => 'doc.content.copy' as const,\n },\n download: Object.assign(() => 'doc.download' as const, {\n flattened: () => 'doc.download.flattened' as const,\n }),\n print: Object.assign(() => 'doc.print' as const, {\n high: () => 'doc.print.high' as const,\n }),\n pages: {\n modify: () => 'doc.pages.modify' as const,\n assemble: () => 'doc.pages.assemble' as const,\n },\n forms: {\n read: () => 'doc.forms.read' as const,\n fill: () => 'doc.forms.fill' as const,\n modify: () => 'doc.forms.modify' as const,\n import: () => 'doc.forms.import' as const,\n script: () => 'doc.forms.script' as const,\n submit: () => 'doc.forms.submit' as const,\n },\n annotate: {\n read: () => 'doc.annotate.read' as const,\n modify: () => 'doc.annotate.modify' as const,\n import: () => 'doc.annotate.import' as const,\n },\n metadata: {\n modify: () => 'doc.metadata.modify' as const,\n },\n attachments: {\n modify: () => 'doc.attachments.modify' as const,\n },\n redact: () => 'doc.redact' as const,\n sign: Object.assign(() => 'doc.sign' as const, {\n certify: () => 'doc.sign.certify' as const,\n }),\n },\n} as const;\n\n/**\n * Builder factory for collab scope filters. Each entity:action pair\n * gets a sub-object with the four filter constructors.\n *\n * collab.annotations.create.self() → \"annotations:create:self\"\n * collab.annotations.create.group(\"legal\") → \"annotations:create:group=legal\"\n * collab.annotations.update.group(\"4\") → \"annotations:update:group=4\"\n * collab.annotations.delete.createdBy(\"u-7\") → \"annotations:delete:createdBy=u-7\"\n * collab.annotations.setGroup.group(\"legal\") → \"annotations:set-group:group=legal\"\n * collab.annotations.all.all() → \"annotations:*:all\" (action wildcard)\n * collab.fields.fill.group(\"buyer\") → \"fields:fill:group=buyer\"\n * collab.fields.sign.group(\"buyer\") → \"fields:sign:group=buyer\"\n * collab.fields.all.group(\"seller\") → \"fields:*:group=seller\"\n *\n * On create, the filter is evaluated against the caller's own identity\n * (no impersonation), so `:self` and `:all` trivially pass; `:group=X`\n * is the meaningful filter — it constrains creation to callers whose\n * default group is X.\n */\nexport const collab = {\n annotations: {\n create: makeFilterBuilder('annotations', 'create'),\n update: makeFilterBuilder('annotations', 'update'),\n delete: makeFilterBuilder('annotations', 'delete'),\n setGroup: makeGroupFilterBuilder('annotations', 'set-group'),\n /** Action wildcard — matches create, update, delete, and set-group with the given filter. */\n all: makeFilterBuilder('annotations', '*'),\n },\n /** Form fields, by group: a field records no creator, so only `:all` and `:group=X`. */\n fields: {\n fill: makeGroupFilterBuilder('fields', 'fill'),\n sign: makeGroupFilterBuilder('fields', 'sign'),\n setGroup: makeGroupFilterBuilder('fields', 'set-group'),\n /** Action wildcard — matches fill, sign, and set-group with the given filter. */\n all: makeGroupFilterBuilder('fields', '*'),\n },\n} as const;\n\ninterface FilterBuilder {\n all(): string;\n self(): string;\n createdBy(userId: string): string;\n group(groupId: string): string;\n}\n\nfunction makeFilterBuilder(entity: string, action: string): FilterBuilder {\n return {\n all: () => `${entity}:${action}:all`,\n self: () => `${entity}:${action}:self`,\n createdBy: (userId: string) => `${entity}:${action}:createdBy=${userId}`,\n group: (groupId: string) => `${entity}:${action}:group=${groupId}`,\n };\n}\n\n/**\n * The scopes that take only `:all` and `:group=X`: `set-group`, an\n * assignment authority rather than a per-record filter (assign-to-any vs\n * assign-to-X), and every field scope, since a field records no creator.\n * The builder exposes exactly those two — a typo at JWT mint time is caught\n * by the compiler instead of producing a JWT that fails at verify.\n */\ninterface GroupFilterBuilder {\n all(): string;\n group(groupId: string): string;\n}\n\nfunction makeGroupFilterBuilder(entity: string, action: string): GroupFilterBuilder {\n return {\n all: () => `${entity}:${action}:all`,\n group: (groupId: string) => `${entity}:${action}:group=${groupId}`,\n };\n}\n\n/**\n * Builder for the `pdf.permissions` virtual scope. Returns the literal\n * string; provided as a helper for parity with caps/collab in JWT\n * construction code.\n */\nexport const pdfPermissions = (): 'pdf.permissions' => 'pdf.permissions';\n\n/**\n * Materialise `pdf.permissions` into the concrete capability list it\n * would expand to under the given PDF bit configuration.\n *\n * Useful when the customer wants to start from PDF defaults and then\n * subtract specific capabilities — easier to build the JWT scope array\n * by filtering an explicit list than by composing virtual + denials.\n *\n * const defaults = materializePdfPermissions(pdfBits);\n * const scope = [\n * ...defaults.filter(s => s !== 'doc.text.copy'),\n * 'doc.download',\n * ];\n *\n * This is the one reading of the bits: the scope resolver and the\n * permission advisory both use it. It follows what Acrobat allows on a\n * file with these bits, which is broader than ISO 32000 in two places:\n * bit 4 (\"changing the document\") also allows filling in and signing, and\n * bit 5 (\"copying text and graphics\") governs taking the text out, not\n * finding or selecting it: Acrobat finds and selects text in a file that\n * forbids copying. A search's snippets reproduce the text, so they need\n * `doc.text.copy`.\n */\nexport function materializePdfPermissions(b: PdfBits): DocCapability[] {\n const out = new Set<DocCapability>();\n\n // Always — pdf.permissions means \"give me a working session\"\n out.add('doc.open');\n out.add('doc.render');\n // Reading existing annotations and form values is unconditional —\n // PDF bit 6 governs writes, not visibility.\n out.add('doc.annotate.read');\n out.add('doc.forms.read');\n // Finding and selecting text are too: bit 5 governs taking it out.\n out.add('doc.text.search');\n out.add('doc.text.select');\n\n if (b.bit5) {\n out.add('doc.text.copy');\n out.add('doc.content.copy');\n }\n if (b.bit3) out.add('doc.print');\n if (b.bit12 && b.bit3) out.add('doc.print.high');\n if (b.bit4) {\n out.add('doc.pages.modify');\n out.add('doc.redact');\n out.add('doc.metadata.modify');\n out.add('doc.attachments.modify');\n }\n // Bit 11 assembles pages even when bit 4 is clear; bit 4 includes it.\n if (b.bit4 || b.bit11) out.add('doc.pages.assemble');\n if (b.bit6) out.add('doc.annotate.modify');\n // Signing a signature field is filling it in. Acrobat (and PDFium's form\n // filler) let any of the three bits fill in.\n if (b.bit4 || b.bit6 || b.bit9) {\n out.add('doc.forms.fill');\n out.add('doc.sign');\n }\n // Changing existing fields takes both: Acrobat keeps them in fill mode\n // under bit 4 alone, and offers no form tools under bit 6 or 9 alone.\n if (b.bit6 && b.bit4) out.add('doc.forms.modify');\n\n return [...out];\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAa,OAAO,EAClB,KAAK;CACH,YAAY;CACZ,cAAc;CACd,MAAM;EACJ,cAAc;EACd,YAAY;EACZ,cAAc;CAChB;CACA,SAAS,EACP,YAAY,mBACd;CACA,UAAU,OAAO,aAAa,gBAAyB,EACrD,iBAAiB,yBACnB,CAAC;CACD,OAAO,OAAO,aAAa,aAAsB,EAC/C,YAAY,iBACd,CAAC;CACD,OAAO;EACL,cAAc;EACd,gBAAgB;CAClB;CACA,OAAO;EACL,YAAY;EACZ,YAAY;EACZ,cAAc;EACd,cAAc;EACd,cAAc;EACd,cAAc;CAChB;CACA,UAAU;EACR,YAAY;EACZ,cAAc;EACd,cAAc;CAChB;CACA,UAAU,EACR,cAAc,sBAChB;CACA,aAAa,EACX,cAAc,yBAChB;CACA,cAAc;CACd,MAAM,OAAO,aAAa,YAAqB,EAC7C,eAAe,mBACjB,CAAC;AACH,EACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,SAAS;CACpB,aAAa;EACX,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,UAAU,uBAAuB,eAAe,WAAW;;EAE3D,KAAK,kBAAkB,eAAe,GAAG;CAC3C;;CAEA,QAAQ;EACN,MAAM,uBAAuB,UAAU,MAAM;EAC7C,MAAM,uBAAuB,UAAU,MAAM;EAC7C,UAAU,uBAAuB,UAAU,WAAW;;EAEtD,KAAK,uBAAuB,UAAU,GAAG;CAC3C;AACF;AASA,SAAS,kBAAkB,QAAgB,QAA+B;CACxE,OAAO;EACL,WAAW,GAAG,OAAO,GAAG,OAAO;EAC/B,YAAY,GAAG,OAAO,GAAG,OAAO;EAChC,YAAY,WAAmB,GAAG,OAAO,GAAG,OAAO,aAAa;EAChE,QAAQ,YAAoB,GAAG,OAAO,GAAG,OAAO,SAAS;CAC3D;AACF;AAcA,SAAS,uBAAuB,QAAgB,QAAoC;CAClF,OAAO;EACL,WAAW,GAAG,OAAO,GAAG,OAAO;EAC/B,QAAQ,YAAoB,GAAG,OAAO,GAAG,OAAO,SAAS;CAC3D;AACF;;;;;;AAOA,MAAa,uBAA0C;;;;;;;;;;;;;;;;;;;;;;;;AAyBvD,SAAgB,0BAA0B,GAA6B;CACrE,MAAM,sBAAM,IAAI,IAAmB;CAGnC,IAAI,IAAI,UAAU;CAClB,IAAI,IAAI,YAAY;CAGpB,IAAI,IAAI,mBAAmB;CAC3B,IAAI,IAAI,gBAAgB;CAExB,IAAI,IAAI,iBAAiB;CACzB,IAAI,IAAI,iBAAiB;CAEzB,IAAI,EAAE,MAAM;EACV,IAAI,IAAI,eAAe;EACvB,IAAI,IAAI,kBAAkB;CAC5B;CACA,IAAI,EAAE,MAAM,IAAI,IAAI,WAAW;CAC/B,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,IAAI,gBAAgB;CAC/C,IAAI,EAAE,MAAM;EACV,IAAI,IAAI,kBAAkB;EAC1B,IAAI,IAAI,YAAY;EACpB,IAAI,IAAI,qBAAqB;EAC7B,IAAI,IAAI,wBAAwB;CAClC;CAEA,IAAI,EAAE,QAAQ,EAAE,OAAO,IAAI,IAAI,oBAAoB;CACnD,IAAI,EAAE,MAAM,IAAI,IAAI,qBAAqB;CAGzC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM;EAC9B,IAAI,IAAI,gBAAgB;EACxB,IAAI,IAAI,UAAU;CACpB;CAGA,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,IAAI,kBAAkB;CAEhD,OAAO,CAAC,GAAG,GAAG;AAChB"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
//#region src/auth/scope/builders.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed capability constants for customer-side JWT minting.
|
|
4
|
+
*
|
|
5
|
+
* The shape mirrors the dotted capability name so it reads naturally:
|
|
6
|
+
* caps.doc.text.copy() // "doc.text.copy"
|
|
7
|
+
* caps.doc.download() // "doc.download"
|
|
8
|
+
* caps.doc.download.flattened() // "doc.download.flattened"
|
|
9
|
+
* caps.doc.print.high() // "doc.print.high"
|
|
10
|
+
*
|
|
11
|
+
* Each leaf is a function returning the literal string (as `const`) so
|
|
12
|
+
* TypeScript catches typos at the call site. Wrappers like `download`
|
|
13
|
+
* and `print` are `Object.assign`'d to be callable and carry child
|
|
14
|
+
* properties for the refinement capabilities.
|
|
15
|
+
*/
|
|
16
|
+
const caps = { doc: {
|
|
17
|
+
open: () => "doc.open",
|
|
18
|
+
render: () => "doc.render",
|
|
19
|
+
text: {
|
|
20
|
+
select: () => "doc.text.select",
|
|
21
|
+
copy: () => "doc.text.copy",
|
|
22
|
+
search: () => "doc.text.search"
|
|
23
|
+
},
|
|
24
|
+
content: { copy: () => "doc.content.copy" },
|
|
25
|
+
download: Object.assign(() => "doc.download", { flattened: () => "doc.download.flattened" }),
|
|
26
|
+
print: Object.assign(() => "doc.print", { high: () => "doc.print.high" }),
|
|
27
|
+
pages: {
|
|
28
|
+
modify: () => "doc.pages.modify",
|
|
29
|
+
assemble: () => "doc.pages.assemble"
|
|
30
|
+
},
|
|
31
|
+
forms: {
|
|
32
|
+
read: () => "doc.forms.read",
|
|
33
|
+
fill: () => "doc.forms.fill",
|
|
34
|
+
modify: () => "doc.forms.modify",
|
|
35
|
+
import: () => "doc.forms.import",
|
|
36
|
+
script: () => "doc.forms.script",
|
|
37
|
+
submit: () => "doc.forms.submit"
|
|
38
|
+
},
|
|
39
|
+
annotate: {
|
|
40
|
+
read: () => "doc.annotate.read",
|
|
41
|
+
modify: () => "doc.annotate.modify",
|
|
42
|
+
import: () => "doc.annotate.import"
|
|
43
|
+
},
|
|
44
|
+
metadata: { modify: () => "doc.metadata.modify" },
|
|
45
|
+
attachments: { modify: () => "doc.attachments.modify" },
|
|
46
|
+
redact: () => "doc.redact",
|
|
47
|
+
sign: Object.assign(() => "doc.sign", { certify: () => "doc.sign.certify" })
|
|
48
|
+
} };
|
|
49
|
+
/**
|
|
50
|
+
* Builder factory for collab scope filters. Each entity:action pair
|
|
51
|
+
* gets a sub-object with the four filter constructors.
|
|
52
|
+
*
|
|
53
|
+
* collab.annotations.create.self() → "annotations:create:self"
|
|
54
|
+
* collab.annotations.create.group("legal") → "annotations:create:group=legal"
|
|
55
|
+
* collab.annotations.update.group("4") → "annotations:update:group=4"
|
|
56
|
+
* collab.annotations.delete.createdBy("u-7") → "annotations:delete:createdBy=u-7"
|
|
57
|
+
* collab.annotations.setGroup.group("legal") → "annotations:set-group:group=legal"
|
|
58
|
+
* collab.annotations.all.all() → "annotations:*:all" (action wildcard)
|
|
59
|
+
* collab.fields.fill.group("buyer") → "fields:fill:group=buyer"
|
|
60
|
+
* collab.fields.sign.group("buyer") → "fields:sign:group=buyer"
|
|
61
|
+
* collab.fields.all.group("seller") → "fields:*:group=seller"
|
|
62
|
+
*
|
|
63
|
+
* On create, the filter is evaluated against the caller's own identity
|
|
64
|
+
* (no impersonation), so `:self` and `:all` trivially pass; `:group=X`
|
|
65
|
+
* is the meaningful filter — it constrains creation to callers whose
|
|
66
|
+
* default group is X.
|
|
67
|
+
*/
|
|
68
|
+
const collab = {
|
|
69
|
+
annotations: {
|
|
70
|
+
create: makeFilterBuilder("annotations", "create"),
|
|
71
|
+
update: makeFilterBuilder("annotations", "update"),
|
|
72
|
+
delete: makeFilterBuilder("annotations", "delete"),
|
|
73
|
+
setGroup: makeGroupFilterBuilder("annotations", "set-group"),
|
|
74
|
+
/** Action wildcard — matches create, update, delete, and set-group with the given filter. */
|
|
75
|
+
all: makeFilterBuilder("annotations", "*")
|
|
76
|
+
},
|
|
77
|
+
/** Form fields, by group: a field records no creator, so only `:all` and `:group=X`. */
|
|
78
|
+
fields: {
|
|
79
|
+
fill: makeGroupFilterBuilder("fields", "fill"),
|
|
80
|
+
sign: makeGroupFilterBuilder("fields", "sign"),
|
|
81
|
+
setGroup: makeGroupFilterBuilder("fields", "set-group"),
|
|
82
|
+
/** Action wildcard — matches fill, sign, and set-group with the given filter. */
|
|
83
|
+
all: makeGroupFilterBuilder("fields", "*")
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
function makeFilterBuilder(entity, action) {
|
|
87
|
+
return {
|
|
88
|
+
all: () => `${entity}:${action}:all`,
|
|
89
|
+
self: () => `${entity}:${action}:self`,
|
|
90
|
+
createdBy: (userId) => `${entity}:${action}:createdBy=${userId}`,
|
|
91
|
+
group: (groupId) => `${entity}:${action}:group=${groupId}`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function makeGroupFilterBuilder(entity, action) {
|
|
95
|
+
return {
|
|
96
|
+
all: () => `${entity}:${action}:all`,
|
|
97
|
+
group: (groupId) => `${entity}:${action}:group=${groupId}`
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Builder for the `pdf.permissions` virtual scope. Returns the literal
|
|
102
|
+
* string; provided as a helper for parity with caps/collab in JWT
|
|
103
|
+
* construction code.
|
|
104
|
+
*/
|
|
105
|
+
const pdfPermissions = () => "pdf.permissions";
|
|
106
|
+
/**
|
|
107
|
+
* Materialise `pdf.permissions` into the concrete capability list it
|
|
108
|
+
* would expand to under the given PDF bit configuration.
|
|
109
|
+
*
|
|
110
|
+
* Useful when the customer wants to start from PDF defaults and then
|
|
111
|
+
* subtract specific capabilities — easier to build the JWT scope array
|
|
112
|
+
* by filtering an explicit list than by composing virtual + denials.
|
|
113
|
+
*
|
|
114
|
+
* const defaults = materializePdfPermissions(pdfBits);
|
|
115
|
+
* const scope = [
|
|
116
|
+
* ...defaults.filter(s => s !== 'doc.text.copy'),
|
|
117
|
+
* 'doc.download',
|
|
118
|
+
* ];
|
|
119
|
+
*
|
|
120
|
+
* This is the one reading of the bits: the scope resolver and the
|
|
121
|
+
* permission advisory both use it. It follows what Acrobat allows on a
|
|
122
|
+
* file with these bits, which is broader than ISO 32000 in two places:
|
|
123
|
+
* bit 4 ("changing the document") also allows filling in and signing, and
|
|
124
|
+
* bit 5 ("copying text and graphics") governs taking the text out, not
|
|
125
|
+
* finding or selecting it: Acrobat finds and selects text in a file that
|
|
126
|
+
* forbids copying. A search's snippets reproduce the text, so they need
|
|
127
|
+
* `doc.text.copy`.
|
|
128
|
+
*/
|
|
129
|
+
function materializePdfPermissions(b) {
|
|
130
|
+
const out = /* @__PURE__ */ new Set();
|
|
131
|
+
out.add("doc.open");
|
|
132
|
+
out.add("doc.render");
|
|
133
|
+
out.add("doc.annotate.read");
|
|
134
|
+
out.add("doc.forms.read");
|
|
135
|
+
out.add("doc.text.search");
|
|
136
|
+
out.add("doc.text.select");
|
|
137
|
+
if (b.bit5) {
|
|
138
|
+
out.add("doc.text.copy");
|
|
139
|
+
out.add("doc.content.copy");
|
|
140
|
+
}
|
|
141
|
+
if (b.bit3) out.add("doc.print");
|
|
142
|
+
if (b.bit12 && b.bit3) out.add("doc.print.high");
|
|
143
|
+
if (b.bit4) {
|
|
144
|
+
out.add("doc.pages.modify");
|
|
145
|
+
out.add("doc.redact");
|
|
146
|
+
out.add("doc.metadata.modify");
|
|
147
|
+
out.add("doc.attachments.modify");
|
|
148
|
+
}
|
|
149
|
+
if (b.bit4 || b.bit11) out.add("doc.pages.assemble");
|
|
150
|
+
if (b.bit6) out.add("doc.annotate.modify");
|
|
151
|
+
if (b.bit4 || b.bit6 || b.bit9) {
|
|
152
|
+
out.add("doc.forms.fill");
|
|
153
|
+
out.add("doc.sign");
|
|
154
|
+
}
|
|
155
|
+
if (b.bit6 && b.bit4) out.add("doc.forms.modify");
|
|
156
|
+
return [...out];
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
Object.defineProperty(exports, "caps", {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
get: function() {
|
|
162
|
+
return caps;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
Object.defineProperty(exports, "collab", {
|
|
166
|
+
enumerable: true,
|
|
167
|
+
get: function() {
|
|
168
|
+
return collab;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
Object.defineProperty(exports, "materializePdfPermissions", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
get: function() {
|
|
174
|
+
return materializePdfPermissions;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
Object.defineProperty(exports, "pdfPermissions", {
|
|
178
|
+
enumerable: true,
|
|
179
|
+
get: function() {
|
|
180
|
+
return pdfPermissions;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
//# sourceMappingURL=builders-Cgdp_YCn.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders-Cgdp_YCn.cjs","names":[],"sources":["../src/auth/scope/builders.ts"],"sourcesContent":["import type { DocCapability, PdfBits } from './types';\n\n/**\n * Typed capability constants for customer-side JWT minting.\n *\n * The shape mirrors the dotted capability name so it reads naturally:\n * caps.doc.text.copy() // \"doc.text.copy\"\n * caps.doc.download() // \"doc.download\"\n * caps.doc.download.flattened() // \"doc.download.flattened\"\n * caps.doc.print.high() // \"doc.print.high\"\n *\n * Each leaf is a function returning the literal string (as `const`) so\n * TypeScript catches typos at the call site. Wrappers like `download`\n * and `print` are `Object.assign`'d to be callable and carry child\n * properties for the refinement capabilities.\n */\nexport const caps = {\n doc: {\n open: () => 'doc.open' as const,\n render: () => 'doc.render' as const,\n text: {\n select: () => 'doc.text.select' as const,\n copy: () => 'doc.text.copy' as const,\n search: () => 'doc.text.search' as const,\n },\n content: {\n copy: () => 'doc.content.copy' as const,\n },\n download: Object.assign(() => 'doc.download' as const, {\n flattened: () => 'doc.download.flattened' as const,\n }),\n print: Object.assign(() => 'doc.print' as const, {\n high: () => 'doc.print.high' as const,\n }),\n pages: {\n modify: () => 'doc.pages.modify' as const,\n assemble: () => 'doc.pages.assemble' as const,\n },\n forms: {\n read: () => 'doc.forms.read' as const,\n fill: () => 'doc.forms.fill' as const,\n modify: () => 'doc.forms.modify' as const,\n import: () => 'doc.forms.import' as const,\n script: () => 'doc.forms.script' as const,\n submit: () => 'doc.forms.submit' as const,\n },\n annotate: {\n read: () => 'doc.annotate.read' as const,\n modify: () => 'doc.annotate.modify' as const,\n import: () => 'doc.annotate.import' as const,\n },\n metadata: {\n modify: () => 'doc.metadata.modify' as const,\n },\n attachments: {\n modify: () => 'doc.attachments.modify' as const,\n },\n redact: () => 'doc.redact' as const,\n sign: Object.assign(() => 'doc.sign' as const, {\n certify: () => 'doc.sign.certify' as const,\n }),\n },\n} as const;\n\n/**\n * Builder factory for collab scope filters. Each entity:action pair\n * gets a sub-object with the four filter constructors.\n *\n * collab.annotations.create.self() → \"annotations:create:self\"\n * collab.annotations.create.group(\"legal\") → \"annotations:create:group=legal\"\n * collab.annotations.update.group(\"4\") → \"annotations:update:group=4\"\n * collab.annotations.delete.createdBy(\"u-7\") → \"annotations:delete:createdBy=u-7\"\n * collab.annotations.setGroup.group(\"legal\") → \"annotations:set-group:group=legal\"\n * collab.annotations.all.all() → \"annotations:*:all\" (action wildcard)\n * collab.fields.fill.group(\"buyer\") → \"fields:fill:group=buyer\"\n * collab.fields.sign.group(\"buyer\") → \"fields:sign:group=buyer\"\n * collab.fields.all.group(\"seller\") → \"fields:*:group=seller\"\n *\n * On create, the filter is evaluated against the caller's own identity\n * (no impersonation), so `:self` and `:all` trivially pass; `:group=X`\n * is the meaningful filter — it constrains creation to callers whose\n * default group is X.\n */\nexport const collab = {\n annotations: {\n create: makeFilterBuilder('annotations', 'create'),\n update: makeFilterBuilder('annotations', 'update'),\n delete: makeFilterBuilder('annotations', 'delete'),\n setGroup: makeGroupFilterBuilder('annotations', 'set-group'),\n /** Action wildcard — matches create, update, delete, and set-group with the given filter. */\n all: makeFilterBuilder('annotations', '*'),\n },\n /** Form fields, by group: a field records no creator, so only `:all` and `:group=X`. */\n fields: {\n fill: makeGroupFilterBuilder('fields', 'fill'),\n sign: makeGroupFilterBuilder('fields', 'sign'),\n setGroup: makeGroupFilterBuilder('fields', 'set-group'),\n /** Action wildcard — matches fill, sign, and set-group with the given filter. */\n all: makeGroupFilterBuilder('fields', '*'),\n },\n} as const;\n\ninterface FilterBuilder {\n all(): string;\n self(): string;\n createdBy(userId: string): string;\n group(groupId: string): string;\n}\n\nfunction makeFilterBuilder(entity: string, action: string): FilterBuilder {\n return {\n all: () => `${entity}:${action}:all`,\n self: () => `${entity}:${action}:self`,\n createdBy: (userId: string) => `${entity}:${action}:createdBy=${userId}`,\n group: (groupId: string) => `${entity}:${action}:group=${groupId}`,\n };\n}\n\n/**\n * The scopes that take only `:all` and `:group=X`: `set-group`, an\n * assignment authority rather than a per-record filter (assign-to-any vs\n * assign-to-X), and every field scope, since a field records no creator.\n * The builder exposes exactly those two — a typo at JWT mint time is caught\n * by the compiler instead of producing a JWT that fails at verify.\n */\ninterface GroupFilterBuilder {\n all(): string;\n group(groupId: string): string;\n}\n\nfunction makeGroupFilterBuilder(entity: string, action: string): GroupFilterBuilder {\n return {\n all: () => `${entity}:${action}:all`,\n group: (groupId: string) => `${entity}:${action}:group=${groupId}`,\n };\n}\n\n/**\n * Builder for the `pdf.permissions` virtual scope. Returns the literal\n * string; provided as a helper for parity with caps/collab in JWT\n * construction code.\n */\nexport const pdfPermissions = (): 'pdf.permissions' => 'pdf.permissions';\n\n/**\n * Materialise `pdf.permissions` into the concrete capability list it\n * would expand to under the given PDF bit configuration.\n *\n * Useful when the customer wants to start from PDF defaults and then\n * subtract specific capabilities — easier to build the JWT scope array\n * by filtering an explicit list than by composing virtual + denials.\n *\n * const defaults = materializePdfPermissions(pdfBits);\n * const scope = [\n * ...defaults.filter(s => s !== 'doc.text.copy'),\n * 'doc.download',\n * ];\n *\n * This is the one reading of the bits: the scope resolver and the\n * permission advisory both use it. It follows what Acrobat allows on a\n * file with these bits, which is broader than ISO 32000 in two places:\n * bit 4 (\"changing the document\") also allows filling in and signing, and\n * bit 5 (\"copying text and graphics\") governs taking the text out, not\n * finding or selecting it: Acrobat finds and selects text in a file that\n * forbids copying. A search's snippets reproduce the text, so they need\n * `doc.text.copy`.\n */\nexport function materializePdfPermissions(b: PdfBits): DocCapability[] {\n const out = new Set<DocCapability>();\n\n // Always — pdf.permissions means \"give me a working session\"\n out.add('doc.open');\n out.add('doc.render');\n // Reading existing annotations and form values is unconditional —\n // PDF bit 6 governs writes, not visibility.\n out.add('doc.annotate.read');\n out.add('doc.forms.read');\n // Finding and selecting text are too: bit 5 governs taking it out.\n out.add('doc.text.search');\n out.add('doc.text.select');\n\n if (b.bit5) {\n out.add('doc.text.copy');\n out.add('doc.content.copy');\n }\n if (b.bit3) out.add('doc.print');\n if (b.bit12 && b.bit3) out.add('doc.print.high');\n if (b.bit4) {\n out.add('doc.pages.modify');\n out.add('doc.redact');\n out.add('doc.metadata.modify');\n out.add('doc.attachments.modify');\n }\n // Bit 11 assembles pages even when bit 4 is clear; bit 4 includes it.\n if (b.bit4 || b.bit11) out.add('doc.pages.assemble');\n if (b.bit6) out.add('doc.annotate.modify');\n // Signing a signature field is filling it in. Acrobat (and PDFium's form\n // filler) let any of the three bits fill in.\n if (b.bit4 || b.bit6 || b.bit9) {\n out.add('doc.forms.fill');\n out.add('doc.sign');\n }\n // Changing existing fields takes both: Acrobat keeps them in fill mode\n // under bit 4 alone, and offers no form tools under bit 6 or 9 alone.\n if (b.bit6 && b.bit4) out.add('doc.forms.modify');\n\n return [...out];\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAa,OAAO,EAClB,KAAK;CACH,YAAY;CACZ,cAAc;CACd,MAAM;EACJ,cAAc;EACd,YAAY;EACZ,cAAc;CAChB;CACA,SAAS,EACP,YAAY,mBACd;CACA,UAAU,OAAO,aAAa,gBAAyB,EACrD,iBAAiB,yBACnB,CAAC;CACD,OAAO,OAAO,aAAa,aAAsB,EAC/C,YAAY,iBACd,CAAC;CACD,OAAO;EACL,cAAc;EACd,gBAAgB;CAClB;CACA,OAAO;EACL,YAAY;EACZ,YAAY;EACZ,cAAc;EACd,cAAc;EACd,cAAc;EACd,cAAc;CAChB;CACA,UAAU;EACR,YAAY;EACZ,cAAc;EACd,cAAc;CAChB;CACA,UAAU,EACR,cAAc,sBAChB;CACA,aAAa,EACX,cAAc,yBAChB;CACA,cAAc;CACd,MAAM,OAAO,aAAa,YAAqB,EAC7C,eAAe,mBACjB,CAAC;AACH,EACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,SAAS;CACpB,aAAa;EACX,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,QAAQ,kBAAkB,eAAe,QAAQ;EACjD,UAAU,uBAAuB,eAAe,WAAW;;EAE3D,KAAK,kBAAkB,eAAe,GAAG;CAC3C;;CAEA,QAAQ;EACN,MAAM,uBAAuB,UAAU,MAAM;EAC7C,MAAM,uBAAuB,UAAU,MAAM;EAC7C,UAAU,uBAAuB,UAAU,WAAW;;EAEtD,KAAK,uBAAuB,UAAU,GAAG;CAC3C;AACF;AASA,SAAS,kBAAkB,QAAgB,QAA+B;CACxE,OAAO;EACL,WAAW,GAAG,OAAO,GAAG,OAAO;EAC/B,YAAY,GAAG,OAAO,GAAG,OAAO;EAChC,YAAY,WAAmB,GAAG,OAAO,GAAG,OAAO,aAAa;EAChE,QAAQ,YAAoB,GAAG,OAAO,GAAG,OAAO,SAAS;CAC3D;AACF;AAcA,SAAS,uBAAuB,QAAgB,QAAoC;CAClF,OAAO;EACL,WAAW,GAAG,OAAO,GAAG,OAAO;EAC/B,QAAQ,YAAoB,GAAG,OAAO,GAAG,OAAO,SAAS;CAC3D;AACF;;;;;;AAOA,MAAa,uBAA0C;;;;;;;;;;;;;;;;;;;;;;;;AAyBvD,SAAgB,0BAA0B,GAA6B;CACrE,MAAM,sBAAM,IAAI,IAAmB;CAGnC,IAAI,IAAI,UAAU;CAClB,IAAI,IAAI,YAAY;CAGpB,IAAI,IAAI,mBAAmB;CAC3B,IAAI,IAAI,gBAAgB;CAExB,IAAI,IAAI,iBAAiB;CACzB,IAAI,IAAI,iBAAiB;CAEzB,IAAI,EAAE,MAAM;EACV,IAAI,IAAI,eAAe;EACvB,IAAI,IAAI,kBAAkB;CAC5B;CACA,IAAI,EAAE,MAAM,IAAI,IAAI,WAAW;CAC/B,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,IAAI,gBAAgB;CAC/C,IAAI,EAAE,MAAM;EACV,IAAI,IAAI,kBAAkB;EAC1B,IAAI,IAAI,YAAY;EACpB,IAAI,IAAI,qBAAqB;EAC7B,IAAI,IAAI,wBAAwB;CAClC;CAEA,IAAI,EAAE,QAAQ,EAAE,OAAO,IAAI,IAAI,oBAAoB;CACnD,IAAI,EAAE,MAAM,IAAI,IAAI,qBAAqB;CAGzC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM;EAC9B,IAAI,IAAI,gBAAgB;EACxB,IAAI,IAAI,UAAU;CACpB;CAGA,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,IAAI,kBAAkB;CAEhD,OAAO,CAAC,GAAG,GAAG;AAChB"}
|