@keithadler/frostjs 0.1.0
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/LICENSE +21 -0
- package/README.md +568 -0
- package/dist/baseline.d.ts +18 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +56 -0
- package/dist/baseline.js.map +1 -0
- package/dist/changed.d.ts +15 -0
- package/dist/changed.d.ts.map +1 -0
- package/dist/changed.js +93 -0
- package/dist/changed.js.map +1 -0
- package/dist/cli/args.d.ts +37 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +200 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +8 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/run.d.ts +9 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +404 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/discover/index.d.ts +15 -0
- package/dist/discover/index.d.ts.map +1 -0
- package/dist/discover/index.js +70 -0
- package/dist/discover/index.js.map +1 -0
- package/dist/eslint.d.ts +103 -0
- package/dist/eslint.d.ts.map +1 -0
- package/dist/eslint.js +111 -0
- package/dist/eslint.js.map +1 -0
- package/dist/extract/annotations.d.ts +5 -0
- package/dist/extract/annotations.d.ts.map +1 -0
- package/dist/extract/annotations.js +5 -0
- package/dist/extract/annotations.js.map +1 -0
- package/dist/extract/ast.d.ts +45 -0
- package/dist/extract/ast.d.ts.map +1 -0
- package/dist/extract/ast.js +60 -0
- package/dist/extract/ast.js.map +1 -0
- package/dist/extract/capability.d.ts +22 -0
- package/dist/extract/capability.d.ts.map +1 -0
- package/dist/extract/capability.js +2 -0
- package/dist/extract/capability.js.map +1 -0
- package/dist/extract/html.d.ts +15 -0
- package/dist/extract/html.d.ts.map +1 -0
- package/dist/extract/html.js +69 -0
- package/dist/extract/html.js.map +1 -0
- package/dist/extract/index.d.ts +9 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +95 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/recognizers/codegen.d.ts +10 -0
- package/dist/extract/recognizers/codegen.d.ts.map +1 -0
- package/dist/extract/recognizers/codegen.js +39 -0
- package/dist/extract/recognizers/codegen.js.map +1 -0
- package/dist/extract/recognizers/dom-escape.d.ts +11 -0
- package/dist/extract/recognizers/dom-escape.d.ts.map +1 -0
- package/dist/extract/recognizers/dom-escape.js +58 -0
- package/dist/extract/recognizers/dom-escape.js.map +1 -0
- package/dist/extract/recognizers/globals.d.ts +9 -0
- package/dist/extract/recognizers/globals.d.ts.map +1 -0
- package/dist/extract/recognizers/globals.js +121 -0
- package/dist/extract/recognizers/globals.js.map +1 -0
- package/dist/extract/recognizers/identity.d.ts +10 -0
- package/dist/extract/recognizers/identity.d.ts.map +1 -0
- package/dist/extract/recognizers/identity.js +79 -0
- package/dist/extract/recognizers/identity.js.map +1 -0
- package/dist/extract/recognizers/navigation.d.ts +12 -0
- package/dist/extract/recognizers/navigation.d.ts.map +1 -0
- package/dist/extract/recognizers/navigation.js +110 -0
- package/dist/extract/recognizers/navigation.js.map +1 -0
- package/dist/extract/recognizers/network.d.ts +11 -0
- package/dist/extract/recognizers/network.d.ts.map +1 -0
- package/dist/extract/recognizers/network.js +41 -0
- package/dist/extract/recognizers/network.js.map +1 -0
- package/dist/extract/recognizers/resolve.d.ts +37 -0
- package/dist/extract/recognizers/resolve.d.ts.map +1 -0
- package/dist/extract/recognizers/resolve.js +72 -0
- package/dist/extract/recognizers/resolve.js.map +1 -0
- package/dist/extract/recognizers/storage.d.ts +9 -0
- package/dist/extract/recognizers/storage.d.ts.map +1 -0
- package/dist/extract/recognizers/storage.js +37 -0
- package/dist/extract/recognizers/storage.js.map +1 -0
- package/dist/extract/recognizers/types.d.ts +38 -0
- package/dist/extract/recognizers/types.d.ts.map +1 -0
- package/dist/extract/recognizers/types.js +25 -0
- package/dist/extract/recognizers/types.js.map +1 -0
- package/dist/extract/recognizers/worker.d.ts +11 -0
- package/dist/extract/recognizers/worker.d.ts.map +1 -0
- package/dist/extract/recognizers/worker.js +41 -0
- package/dist/extract/recognizers/worker.js.map +1 -0
- package/dist/extract/scope.d.ts +23 -0
- package/dist/extract/scope.d.ts.map +1 -0
- package/dist/extract/scope.js +299 -0
- package/dist/extract/scope.js.map +1 -0
- package/dist/extract/suppress.d.ts +21 -0
- package/dist/extract/suppress.d.ts.map +1 -0
- package/dist/extract/suppress.js +42 -0
- package/dist/extract/suppress.js.map +1 -0
- package/dist/extract/target.d.ts +34 -0
- package/dist/extract/target.d.ts.map +1 -0
- package/dist/extract/target.js +81 -0
- package/dist/extract/target.js.map +1 -0
- package/dist/extract/typescript.d.ts +12 -0
- package/dist/extract/typescript.d.ts.map +1 -0
- package/dist/extract/typescript.js +56 -0
- package/dist/extract/typescript.js.map +1 -0
- package/dist/extract/walk.d.ts +14 -0
- package/dist/extract/walk.d.ts.map +1 -0
- package/dist/extract/walk.js +70 -0
- package/dist/extract/walk.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +10 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +79 -0
- package/dist/init.js.map +1 -0
- package/dist/policy/compile.d.ts +56 -0
- package/dist/policy/compile.d.ts.map +1 -0
- package/dist/policy/compile.js +78 -0
- package/dist/policy/compile.js.map +1 -0
- package/dist/policy/config.d.ts +18 -0
- package/dist/policy/config.d.ts.map +1 -0
- package/dist/policy/config.js +70 -0
- package/dist/policy/config.js.map +1 -0
- package/dist/policy/csp.d.ts +19 -0
- package/dist/policy/csp.d.ts.map +1 -0
- package/dist/policy/csp.js +47 -0
- package/dist/policy/csp.js.map +1 -0
- package/dist/policy/glob.d.ts +12 -0
- package/dist/policy/glob.d.ts.map +1 -0
- package/dist/policy/glob.js +63 -0
- package/dist/policy/glob.js.map +1 -0
- package/dist/policy/index.d.ts +47 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +34 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/parse.d.ts +51 -0
- package/dist/policy/parse.d.ts.map +1 -0
- package/dist/policy/parse.js +352 -0
- package/dist/policy/parse.js.map +1 -0
- package/dist/policy/vocabulary.d.ts +15 -0
- package/dist/policy/vocabulary.d.ts.map +1 -0
- package/dist/policy/vocabulary.js +99 -0
- package/dist/policy/vocabulary.js.map +1 -0
- package/dist/registry.d.ts +45 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +85 -0
- package/dist/registry.js.map +1 -0
- package/dist/report/github.d.ts +10 -0
- package/dist/report/github.d.ts.map +1 -0
- package/dist/report/github.js +31 -0
- package/dist/report/github.js.map +1 -0
- package/dist/report/json.d.ts +44 -0
- package/dist/report/json.d.ts.map +1 -0
- package/dist/report/json.js +40 -0
- package/dist/report/json.js.map +1 -0
- package/dist/report/sarif.d.ts +10 -0
- package/dist/report/sarif.d.ts.map +1 -0
- package/dist/report/sarif.js +64 -0
- package/dist/report/sarif.js.map +1 -0
- package/dist/report/summary.d.ts +9 -0
- package/dist/report/summary.d.ts.map +1 -0
- package/dist/report/summary.js +67 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/text.d.ts +37 -0
- package/dist/report/text.d.ts.map +1 -0
- package/dist/report/text.js +81 -0
- package/dist/report/text.js.map +1 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +131 -0
- package/dist/sync.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Finding and loading the policy file. */
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { compile } from "./compile.js";
|
|
5
|
+
import { parsePolicy } from "./parse.js";
|
|
6
|
+
export const POLICY_FILENAME = "frostjs.policy";
|
|
7
|
+
/** The deepest directory containing every input (a file counts as its directory). */
|
|
8
|
+
export function commonAncestor(inputs) {
|
|
9
|
+
const dirs = inputs.map((p) => {
|
|
10
|
+
const abs = path.resolve(p);
|
|
11
|
+
let isDir = false;
|
|
12
|
+
try {
|
|
13
|
+
isDir = fs.statSync(abs).isDirectory();
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// A missing path is reported by discover(); treat it as a file here.
|
|
17
|
+
}
|
|
18
|
+
return isDir ? abs : path.dirname(abs);
|
|
19
|
+
});
|
|
20
|
+
if (dirs.length === 0)
|
|
21
|
+
return process.cwd();
|
|
22
|
+
let common = dirs[0].split(path.sep);
|
|
23
|
+
for (const d of dirs.slice(1)) {
|
|
24
|
+
const parts = d.split(path.sep);
|
|
25
|
+
let i = 0;
|
|
26
|
+
while (i < common.length && i < parts.length && common[i] === parts[i])
|
|
27
|
+
i++;
|
|
28
|
+
common = common.slice(0, i);
|
|
29
|
+
}
|
|
30
|
+
return common.join(path.sep) || path.sep;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Walk up from `start` looking for frostjs.policy. `stopAt`, when given, is the
|
|
34
|
+
* last directory searched. Returns the absolute path or null.
|
|
35
|
+
*/
|
|
36
|
+
export function findPolicyFile(start, stopAt) {
|
|
37
|
+
let dir = path.resolve(start);
|
|
38
|
+
const stop = stopAt ? path.resolve(stopAt) : null;
|
|
39
|
+
for (;;) {
|
|
40
|
+
const candidate = path.join(dir, POLICY_FILENAME);
|
|
41
|
+
if (fs.existsSync(candidate))
|
|
42
|
+
return candidate;
|
|
43
|
+
if (dir === stop)
|
|
44
|
+
return null;
|
|
45
|
+
const parent = path.dirname(dir);
|
|
46
|
+
if (parent === dir)
|
|
47
|
+
return null;
|
|
48
|
+
dir = parent;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Today as YYYY-MM-DD, the form every expiry check uses. */
|
|
52
|
+
export function isoToday() {
|
|
53
|
+
return new Date().toISOString().slice(0, 10);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Read and compile a policy file. Throws PolicyError when it cannot be
|
|
57
|
+
* read as a policy, or a plain Error when the file cannot be read at all.
|
|
58
|
+
* `shownAs` is the name used in messages, typically relative to the cwd.
|
|
59
|
+
*/
|
|
60
|
+
export function compilePolicyFile(policyFile, today, shownAs = policyFile) {
|
|
61
|
+
let source;
|
|
62
|
+
try {
|
|
63
|
+
source = fs.readFileSync(policyFile, "utf8");
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
throw new Error(`cannot read policy ${shownAs}: ${e.code ?? e.message}`);
|
|
67
|
+
}
|
|
68
|
+
return compile(parsePolicy(source, shownAs), { today });
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/policy/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a Content-Security-Policy header from a compiled policy. CSP is
|
|
3
|
+
* the runtime backstop; this is the build-time gate. Only directives the
|
|
4
|
+
* policy actually determines are emitted:
|
|
5
|
+
*
|
|
6
|
+
* connect-src from `may reach` hosts; `may use the network` means *;
|
|
7
|
+
* nothing granted means 'none'
|
|
8
|
+
* script-src 'self', plus 'unsafe-eval' when code generation is granted,
|
|
9
|
+
* plus any `may reach` hosts when dynamic import is granted
|
|
10
|
+
* worker-src 'self' plus `may reach` hosts when workers are granted
|
|
11
|
+
*
|
|
12
|
+
* Path-scoped grants still count: a header covers the whole page. Expired
|
|
13
|
+
* grants do not. Forbids narrow nothing here, since CSP cannot express
|
|
14
|
+
* "everything except"; the build-time gate enforces those.
|
|
15
|
+
*/
|
|
16
|
+
import { type Policy } from "./compile.js";
|
|
17
|
+
/** The Content-Security-Policy header string the policy implies, for the date it was compiled against. */
|
|
18
|
+
export declare function csp(policy: Policy): string;
|
|
19
|
+
//# sourceMappingURL=csp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csp.d.ts","sourceRoot":"","sources":["../../src/policy/csp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAGzE,0GAA0G;AAC1G,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA2B1C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a Content-Security-Policy header from a compiled policy. CSP is
|
|
3
|
+
* the runtime backstop; this is the build-time gate. Only directives the
|
|
4
|
+
* policy actually determines are emitted:
|
|
5
|
+
*
|
|
6
|
+
* connect-src from `may reach` hosts; `may use the network` means *;
|
|
7
|
+
* nothing granted means 'none'
|
|
8
|
+
* script-src 'self', plus 'unsafe-eval' when code generation is granted,
|
|
9
|
+
* plus any `may reach` hosts when dynamic import is granted
|
|
10
|
+
* worker-src 'self' plus `may reach` hosts when workers are granted
|
|
11
|
+
*
|
|
12
|
+
* Path-scoped grants still count: a header covers the whole page. Expired
|
|
13
|
+
* grants do not. Forbids narrow nothing here, since CSP cannot express
|
|
14
|
+
* "everything except"; the build-time gate enforces those.
|
|
15
|
+
*/
|
|
16
|
+
import { isExpired, matchesCapability } from "./compile.js";
|
|
17
|
+
import { SAME_ORIGIN } from "../extract/target.js";
|
|
18
|
+
/** The Content-Security-Policy header string the policy implies, for the date it was compiled against. */
|
|
19
|
+
export function csp(policy) {
|
|
20
|
+
const rules = policy.rules.filter((r) => r.verb === "may" && !isExpired(r, policy.today));
|
|
21
|
+
const granted = (capability) => rules.some((r) => matchesCapability(r.capability, capability));
|
|
22
|
+
const directives = [];
|
|
23
|
+
// connect-src
|
|
24
|
+
const net = rules.filter((r) => matchesCapability(r.capability, "network.fetch"));
|
|
25
|
+
const anyDestination = net.some((r) => r.hosts.length === 0);
|
|
26
|
+
const hosts = [...new Set(net.flatMap((r) => r.hosts.map((h) => (h === SAME_ORIGIN ? "'self'" : h))))];
|
|
27
|
+
if (anyDestination)
|
|
28
|
+
directives.push("connect-src *");
|
|
29
|
+
else if (hosts.length > 0)
|
|
30
|
+
directives.push(`connect-src ${hosts.join(" ")}`);
|
|
31
|
+
else
|
|
32
|
+
directives.push("connect-src 'none'");
|
|
33
|
+
/** 'self' plus every reachable host, or * when any destination is granted. */
|
|
34
|
+
const selfAndHosts = () => ["'self'", ...(anyDestination ? ["*"] : hosts.filter((h) => h !== "'self'"))].join(" ");
|
|
35
|
+
// script-src
|
|
36
|
+
let script = "'self'";
|
|
37
|
+
if (granted("codegen.eval") || granted("codegen.function"))
|
|
38
|
+
script += " 'unsafe-eval'";
|
|
39
|
+
if (granted("network.import"))
|
|
40
|
+
script += selfAndHosts().slice("'self'".length);
|
|
41
|
+
directives.push(`script-src ${script}`);
|
|
42
|
+
// worker-src
|
|
43
|
+
if (granted("worker.dedicated") || granted("worker.service"))
|
|
44
|
+
directives.push(`worker-src ${selfAndHosts()}`);
|
|
45
|
+
return directives.join("; ");
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=csp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csp.js","sourceRoot":"","sources":["../../src/policy/csp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAe,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,0GAA0G;AAC1G,MAAM,UAAU,GAAG,CAAC,MAAc;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,CAAC,UAAkB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,cAAc;IACd,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;IAClF,MAAM,cAAc,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvG,IAAI,cAAc;QAAE,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;SAChD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;;QACxE,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE3C,8EAA8E;IAC9E,MAAM,YAAY,GAAG,GAAW,EAAE,CAChC,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1F,aAAa;IACb,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,IAAI,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAAE,MAAM,IAAI,gBAAgB,CAAC;IACvF,IAAI,OAAO,CAAC,gBAAgB,CAAC;QAAE,MAAM,IAAI,YAAY,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/E,UAAU,CAAC,IAAI,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;IAExC,aAAa;IACb,IAAI,OAAO,CAAC,kBAAkB,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,cAAc,YAAY,EAAE,EAAE,CAAC,CAAC;IAE9G,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path globs for policy scoping. Deliberately small: `*` within a segment,
|
|
3
|
+
* `**` across segments, `?` one character. Patterns and paths are compared
|
|
4
|
+
* with forward slashes. A pattern with no slash matches the basename at any
|
|
5
|
+
* depth (gitignore style); a plain path with no glob characters also
|
|
6
|
+
* matches everything beneath it, so `in "src/legacy"` reads naturally.
|
|
7
|
+
*/
|
|
8
|
+
/** Escape a string for literal use inside a RegExp. */
|
|
9
|
+
export declare function escapeRegExp(s: string): string;
|
|
10
|
+
/** True when `file` (a path relative to the policy directory) matches the glob. */
|
|
11
|
+
export declare function matchesGlob(pattern: string, file: string): boolean;
|
|
12
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/policy/glob.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASlE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path globs for policy scoping. Deliberately small: `*` within a segment,
|
|
3
|
+
* `**` across segments, `?` one character. Patterns and paths are compared
|
|
4
|
+
* with forward slashes. A pattern with no slash matches the basename at any
|
|
5
|
+
* depth (gitignore style); a plain path with no glob characters also
|
|
6
|
+
* matches everything beneath it, so `in "src/legacy"` reads naturally.
|
|
7
|
+
*/
|
|
8
|
+
const cache = new Map();
|
|
9
|
+
/** Escape a string for literal use inside a RegExp. */
|
|
10
|
+
export function escapeRegExp(s) {
|
|
11
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12
|
+
}
|
|
13
|
+
/** True when `file` (a path relative to the policy directory) matches the glob. */
|
|
14
|
+
export function matchesGlob(pattern, file) {
|
|
15
|
+
const pat = normalize(pattern);
|
|
16
|
+
const path = normalize(file);
|
|
17
|
+
let rx = cache.get(pat);
|
|
18
|
+
if (!rx) {
|
|
19
|
+
rx = toRegExp(pat);
|
|
20
|
+
cache.set(pat, rx);
|
|
21
|
+
}
|
|
22
|
+
return rx.test(path);
|
|
23
|
+
}
|
|
24
|
+
function normalize(p) {
|
|
25
|
+
let s = p.replace(/\\/g, "/");
|
|
26
|
+
while (s.startsWith("./"))
|
|
27
|
+
s = s.slice(2);
|
|
28
|
+
return s.replace(/\/+$/, "");
|
|
29
|
+
}
|
|
30
|
+
function toRegExp(pat) {
|
|
31
|
+
const hasGlob = /[*?]/.test(pat);
|
|
32
|
+
const anyDepth = !pat.includes("/");
|
|
33
|
+
let out = "";
|
|
34
|
+
for (let i = 0; i < pat.length; i++) {
|
|
35
|
+
const ch = pat[i];
|
|
36
|
+
if (ch === "*") {
|
|
37
|
+
if (pat[i + 1] === "*") {
|
|
38
|
+
// `**/` matches zero or more whole segments; a trailing `**` matches the rest.
|
|
39
|
+
if (pat[i + 2] === "/") {
|
|
40
|
+
out += "(?:.*/)?";
|
|
41
|
+
i += 2;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
out += ".*";
|
|
45
|
+
i += 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
out += "[^/]*";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (ch === "?") {
|
|
53
|
+
out += "[^/]";
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
out += escapeRegExp(ch);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const prefix = anyDepth ? "^(?:.*/)?" : "^";
|
|
60
|
+
const suffix = hasGlob ? "$" : "(?:/.*)?$";
|
|
61
|
+
return new RegExp(prefix + out + suffix);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/policy/glob.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACvB,+EAA+E;gBAC/E,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACvB,GAAG,IAAI,UAAU,CAAC;oBAClB,CAAC,IAAI,CAAC,CAAC;gBACT,CAAC;qBAAM,CAAC;oBACN,GAAG,IAAI,IAAI,CAAC;oBACZ,CAAC,IAAI,CAAC,CAAC;gBACT,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,GAAG,IAAI,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,GAAG,IAAI,MAAM,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC;IAC3C,OAAO,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The policy stage: parse a frostjs.policy, compile it, and decide each
|
|
3
|
+
* CapabilityUse. Everything outside this directory imports from here.
|
|
4
|
+
*/
|
|
5
|
+
import type { CapabilityUse, Confidence } from "../extract/capability.js";
|
|
6
|
+
import { type Policy, type Reason } from "./compile.js";
|
|
7
|
+
import type { Rule } from "./parse.js";
|
|
8
|
+
export { compile, isExpired, matchesCapability, type Policy, type Evaluation, type Reason } from "./compile.js";
|
|
9
|
+
export { parsePolicy, PolicyError, type ParsedPolicy, type Rule } from "./parse.js";
|
|
10
|
+
export { commonAncestor, compilePolicyFile, findPolicyFile, isoToday, POLICY_FILENAME } from "./config.js";
|
|
11
|
+
export { matchesGlob } from "./glob.js";
|
|
12
|
+
export { csp } from "./csp.js";
|
|
13
|
+
export type { Confidence } from "../extract/capability.js";
|
|
14
|
+
/**
|
|
15
|
+
* What became of a use. `allowed` and `denied` come from the policy;
|
|
16
|
+
* `unknown` is a use below the confidence floor (listed, never failing);
|
|
17
|
+
* `suppressed` has an inline `frostjs: ignore`; `baselined` is on record in
|
|
18
|
+
* the baseline file; `unchanged` sits outside the lines a `--changed-since`
|
|
19
|
+
* diff touched. Only `denied` fails the build.
|
|
20
|
+
*/
|
|
21
|
+
export type Verdict = "allowed" | "denied" | "unknown" | "suppressed" | "baselined" | "unchanged";
|
|
22
|
+
export interface Decision {
|
|
23
|
+
use: CapabilityUse;
|
|
24
|
+
verdict: Verdict;
|
|
25
|
+
reason: Reason | null;
|
|
26
|
+
/** The policy rule that decided it, or null for the implicit deny or for unknown. */
|
|
27
|
+
rule: Rule | null;
|
|
28
|
+
}
|
|
29
|
+
/** The policy used when no frostjs.policy exists: nothing is granted. */
|
|
30
|
+
export declare const DENY_ALL: Policy;
|
|
31
|
+
/** Confidence tiers, lowest first. */
|
|
32
|
+
export declare const CONFIDENCE_ORDER: readonly Confidence[];
|
|
33
|
+
/** Uses below this confidence are reported as unknown and never fail the build. */
|
|
34
|
+
export declare const DEFAULT_MIN_CONFIDENCE: Confidence;
|
|
35
|
+
export interface DecideOptions {
|
|
36
|
+
/** Map a use's reported path to the path the policy's globs should see. */
|
|
37
|
+
scopePath?: (use: CapabilityUse) => string;
|
|
38
|
+
minConfidence?: Confidence;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Decide every use against the policy. Allowed uses are allowed at any
|
|
42
|
+
* confidence; a denied use is then suppressed, unknown (below the floor),
|
|
43
|
+
* or denied. An unregistered vendored file is denied whatever the policy
|
|
44
|
+
* says, since no grant can admit a hash nobody reviewed.
|
|
45
|
+
*/
|
|
46
|
+
export declare function decide(uses: readonly CapabilityUse[], policy: Policy, opts?: DecideOptions): Decision[];
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAW,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAChH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC;AAElG,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qFAAqF;IACrF,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAED,yEAAyE;AACzE,eAAO,MAAM,QAAQ,EAAE,MAGtB,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,EAAE,SAAS,UAAU,EAAwC,CAAC;AAC3F,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,EAAE,UAAuB,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,MAAM,CAAC;IAC3C,aAAa,CAAC,EAAE,UAAU,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,QAAQ,EAAE,CAU3G"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { compile } from "./compile.js";
|
|
2
|
+
export { compile, isExpired, matchesCapability } from "./compile.js";
|
|
3
|
+
export { parsePolicy, PolicyError } from "./parse.js";
|
|
4
|
+
export { commonAncestor, compilePolicyFile, findPolicyFile, isoToday, POLICY_FILENAME } from "./config.js";
|
|
5
|
+
export { matchesGlob } from "./glob.js";
|
|
6
|
+
export { csp } from "./csp.js";
|
|
7
|
+
/** The policy used when no frostjs.policy exists: nothing is granted. */
|
|
8
|
+
export const DENY_ALL = compile({ file: "(no policy)", name: "deny-all", rules: [], vendored: [], ignore: [] }, { today: "1970-01-01" });
|
|
9
|
+
/** Confidence tiers, lowest first. */
|
|
10
|
+
export const CONFIDENCE_ORDER = ["possible", "probable", "certain"];
|
|
11
|
+
/** Uses below this confidence are reported as unknown and never fail the build. */
|
|
12
|
+
export const DEFAULT_MIN_CONFIDENCE = "probable";
|
|
13
|
+
/**
|
|
14
|
+
* Decide every use against the policy. Allowed uses are allowed at any
|
|
15
|
+
* confidence; a denied use is then suppressed, unknown (below the floor),
|
|
16
|
+
* or denied. An unregistered vendored file is denied whatever the policy
|
|
17
|
+
* says, since no grant can admit a hash nobody reviewed.
|
|
18
|
+
*/
|
|
19
|
+
export function decide(uses, policy, opts = {}) {
|
|
20
|
+
const floor = CONFIDENCE_ORDER.indexOf(opts.minConfidence ?? DEFAULT_MIN_CONFIDENCE);
|
|
21
|
+
return uses.map((use) => {
|
|
22
|
+
if (use.capability === "vendor.unregistered")
|
|
23
|
+
return { use, verdict: "denied", reason: "unregistered", rule: null };
|
|
24
|
+
const e = policy.evaluate(opts.scopePath ? { ...use, file: opts.scopePath(use) } : use);
|
|
25
|
+
if (e.verdict === "allowed")
|
|
26
|
+
return { use, verdict: "allowed", reason: e.reason, rule: e.rule };
|
|
27
|
+
if (use.suppressed)
|
|
28
|
+
return { use, verdict: "suppressed", reason: null, rule: null };
|
|
29
|
+
if (CONFIDENCE_ORDER.indexOf(use.confidence) < floor)
|
|
30
|
+
return { use, verdict: "unknown", reason: null, rule: null };
|
|
31
|
+
return { use, verdict: "denied", reason: e.reason, rule: e.rule };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA4B,MAAM,cAAc,CAAC;AAGjE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAA6C,MAAM,cAAc,CAAC;AAChH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAgC,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAoB/B,yEAAyE;AACzE,MAAM,CAAC,MAAM,QAAQ,GAAW,OAAO,CACrC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAC9E,EAAE,KAAK,EAAE,YAAY,EAAE,CACxB,CAAC;AAEF,sCAAsC;AACtC,MAAM,CAAC,MAAM,gBAAgB,GAA0B,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAC3F,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAe,UAAU,CAAC;AAQ7D;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,IAA8B,EAAE,MAAc,EAAE,OAAsB,EAAE;IAC7F,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,IAAI,sBAAsB,CAAC,CAAC;IACrF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,UAAU,KAAK,qBAAqB;YAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACpH,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxF,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChG,IAAI,GAAG,CAAC,UAAU;YAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACpF,IAAI,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,KAAK;YAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACnH,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type Verb = "may" | "forbid";
|
|
2
|
+
export interface Rule {
|
|
3
|
+
verb: Verb;
|
|
4
|
+
/** Capability code or family, or "*" for everything. */
|
|
5
|
+
capability: string;
|
|
6
|
+
/** For `may reach` / `forbid reaching`: host patterns. Empty means any destination. */
|
|
7
|
+
hosts: string[];
|
|
8
|
+
/** Path globs the rule is scoped to; empty means everywhere. */
|
|
9
|
+
paths: string[];
|
|
10
|
+
/** ISO date (YYYY-MM-DD) after which a `may` rule no longer grants, or null. */
|
|
11
|
+
until: string | null;
|
|
12
|
+
/** The trailing comment, if any. */
|
|
13
|
+
hint: string;
|
|
14
|
+
/** 1-based line in the policy file, for reports. */
|
|
15
|
+
line: number;
|
|
16
|
+
/** The rule text as written, trimmed, without its comment. */
|
|
17
|
+
text: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ParsedPolicy {
|
|
20
|
+
file: string;
|
|
21
|
+
name: string;
|
|
22
|
+
rules: Rule[];
|
|
23
|
+
/** Globs, relative to the policy directory, of third-party files checked by fingerprint rather than analyzed. */
|
|
24
|
+
vendored: string[];
|
|
25
|
+
/** Globs, relative to the policy directory, of files not analyzed at all (generated bundles, fixtures). */
|
|
26
|
+
ignore: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A policy that cannot be read. The message carries file, line, the source
|
|
30
|
+
* line with a caret under the column, and what to try instead.
|
|
31
|
+
*/
|
|
32
|
+
export declare class PolicyError extends Error {
|
|
33
|
+
readonly file: string;
|
|
34
|
+
readonly line: number;
|
|
35
|
+
/** 1-based. */
|
|
36
|
+
readonly column: number;
|
|
37
|
+
readonly detail: string;
|
|
38
|
+
readonly source: string;
|
|
39
|
+
readonly tryInstead?: string | undefined;
|
|
40
|
+
constructor(file: string, line: number,
|
|
41
|
+
/** 1-based. */
|
|
42
|
+
column: number, detail: string, source: string, tryInstead?: string | undefined);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse a policy file's text. Throws PolicyError at the first line that
|
|
46
|
+
* cannot be read; `file` is used only in messages.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parsePolicy(text: string, file: string): ParsedPolicy;
|
|
49
|
+
/** Year, month (0-based) and day of a validated YYYY-MM-DD string. */
|
|
50
|
+
export declare function ymd(s: string): [number, number, number];
|
|
51
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/policy/parse.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEpC,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gEAAgE;IAChE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gFAAgF;IAChF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,iHAAiH;IACjH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2GAA2G;IAC3G,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,WAAY,SAAQ,KAAK;aAElB,IAAI,EAAE,MAAM;aACZ,IAAI,EAAE,MAAM;IAC5B,eAAe;aACC,MAAM,EAAE,MAAM;aACd,MAAM,EAAE,MAAM;aACd,MAAM,EAAE,MAAM;aACd,UAAU,CAAC,EAAE,MAAM;gBANnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;IAC5B,eAAe;IACC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,YAAA;CAQtC;AAiCD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAsCpE;AAkLD,sEAAsE;AACtE,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAGvD"}
|