@intentius/chant-lexicon-cedar 0.44.8 → 0.44.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -2
- package/dist/agentcore/embed.d.ts +189 -0
- package/dist/agentcore/embed.d.ts.map +1 -0
- package/dist/agentcore/enforcement.d.ts +76 -0
- package/dist/agentcore/enforcement.d.ts.map +1 -0
- package/dist/agentcore/scan.d.ts +46 -0
- package/dist/agentcore/scan.d.ts.map +1 -0
- package/dist/codegen/docs-dogwood.d.ts +21 -0
- package/dist/codegen/docs-dogwood.d.ts.map +1 -0
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/package.d.ts.map +1 -1
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/dogwood/cli.d.ts +247 -0
- package/dist/dogwood/cli.d.ts.map +1 -0
- package/dist/dogwood/event-schema.d.ts +161 -0
- package/dist/dogwood/event-schema.d.ts.map +1 -0
- package/dist/dogwood/index.d.ts +39 -0
- package/dist/dogwood/index.d.ts.map +1 -0
- package/dist/dogwood/macros.d.ts +96 -0
- package/dist/dogwood/macros.d.ts.map +1 -0
- package/dist/dogwood/policy.d.ts +120 -0
- package/dist/dogwood/policy.d.ts.map +1 -0
- package/dist/dogwood/replay-activity.d.ts +196 -0
- package/dist/dogwood/replay-activity.d.ts.map +1 -0
- package/dist/dogwood/replay-op.d.ts +165 -0
- package/dist/dogwood/replay-op.d.ts.map +1 -0
- package/dist/dogwood/scan.d.ts +109 -0
- package/dist/dogwood/scan.d.ts.map +1 -0
- package/dist/dogwood/serialize.d.ts +66 -0
- package/dist/dogwood/serialize.d.ts.map +1 -0
- package/dist/dogwood/temporal.d.ts +259 -0
- package/dist/dogwood/temporal.d.ts.map +1 -0
- package/dist/dogwood/trace.d.ts +215 -0
- package/dist/dogwood/trace.d.ts.map +1 -0
- package/dist/dogwood/upstream.d.ts +41 -0
- package/dist/dogwood/upstream.d.ts.map +1 -0
- package/dist/dogwood/window.d.ts +73 -0
- package/dist/dogwood/window.d.ts.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +15 -3
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/dogwood-helpers.d.ts +63 -0
- package/dist/lint/post-synth/dogwood-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/dwdc010.d.ts +25 -0
- package/dist/lint/post-synth/dwdc010.d.ts.map +1 -0
- package/dist/lint/post-synth/dwdc011.d.ts +19 -0
- package/dist/lint/post-synth/dwdc011.d.ts.map +1 -0
- package/dist/lint/post-synth/dwdc012.d.ts +21 -0
- package/dist/lint/post-synth/dwdc012.d.ts.map +1 -0
- package/dist/lint/post-synth/dwdc013.d.ts +33 -0
- package/dist/lint/post-synth/dwdc013.d.ts.map +1 -0
- package/dist/lint/post-synth/dwde010.d.ts +32 -0
- package/dist/lint/post-synth/dwde010.d.ts.map +1 -0
- package/dist/lint/post-synth/dwde011.d.ts +33 -0
- package/dist/lint/post-synth/dwde011.d.ts.map +1 -0
- package/dist/lint/post-synth/dwds010.d.ts +24 -0
- package/dist/lint/post-synth/dwds010.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +7 -0
- package/dist/okf/rules/DWDC010.md +11 -0
- package/dist/okf/rules/DWDC011.md +11 -0
- package/dist/okf/rules/DWDC012.md +11 -0
- package/dist/okf/rules/DWDC013.md +15 -0
- package/dist/okf/rules/DWDE010.md +11 -0
- package/dist/okf/rules/DWDE011.md +11 -0
- package/dist/okf/rules/DWDS010.md +11 -0
- package/dist/okf/types/Policy.md +1 -0
- package/dist/op/activities/index.d.ts +18 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/policy-text.d.ts +53 -0
- package/dist/policy-text.d.ts.map +1 -0
- package/dist/rules/dogwood-helpers.ts +139 -0
- package/dist/rules/dwdc010.ts +62 -0
- package/dist/rules/dwdc011.ts +61 -0
- package/dist/rules/dwdc012.ts +46 -0
- package/dist/rules/dwdc013.ts +64 -0
- package/dist/rules/dwde010.ts +130 -0
- package/dist/rules/dwde011.ts +108 -0
- package/dist/rules/dwds010.ts +46 -0
- package/dist/serializer.d.ts +10 -18
- package/dist/serializer.d.ts.map +1 -1
- package/dist/skills/chant-cedar-authoring.md +180 -0
- package/dist/skills/chant-cedar-avp-embedding.md +125 -0
- package/dist/skills/chant-cedar-dogwood.md +327 -0
- package/dist/skills/chant-cedar-meta-policy.md +119 -0
- package/package.json +7 -2
- package/src/agentcore/embed.test.ts +254 -0
- package/src/agentcore/embed.ts +399 -0
- package/src/agentcore/enforcement.test.ts +43 -0
- package/src/agentcore/enforcement.ts +92 -0
- package/src/agentcore/scan.ts +119 -0
- package/src/codegen/docs-dogwood.ts +1119 -0
- package/src/codegen/docs.ts +66 -1
- package/src/codegen/package.ts +3 -2
- package/src/config.test.ts +12 -0
- package/src/config.ts +28 -0
- package/src/dogwood/cli.test.ts +513 -0
- package/src/dogwood/cli.ts +666 -0
- package/src/dogwood/event-schema.test.ts +218 -0
- package/src/dogwood/event-schema.ts +318 -0
- package/src/dogwood/index.ts +271 -0
- package/src/dogwood/macros.test.ts +104 -0
- package/src/dogwood/macros.ts +229 -0
- package/src/dogwood/policy.test.ts +94 -0
- package/src/dogwood/policy.ts +141 -0
- package/src/dogwood/replay-activity.test.ts +481 -0
- package/src/dogwood/replay-activity.ts +506 -0
- package/src/dogwood/replay-op.ts +242 -0
- package/src/dogwood/scan.ts +287 -0
- package/src/dogwood/serialize.test.ts +331 -0
- package/src/dogwood/serialize.ts +246 -0
- package/src/dogwood/temporal.test.ts +272 -0
- package/src/dogwood/temporal.ts +592 -0
- package/src/dogwood/testdata/custom-kinds.dwschema +17 -0
- package/src/dogwood/testdata/default-macros.dw +23 -0
- package/src/dogwood/testdata/lowered-read-after-login.json +13 -0
- package/src/dogwood/testdata/max-window-raised.dwschema +25 -0
- package/src/dogwood/testdata/pinned.dwschema +31 -0
- package/src/dogwood/testdata/read-after-login.cedarschema +20 -0
- package/src/dogwood/testdata/read-after-login.dw +17 -0
- package/src/dogwood/testdata/temporal-policies.dw +53 -0
- package/src/dogwood/trace.test.ts +231 -0
- package/src/dogwood/trace.ts +471 -0
- package/src/dogwood/upstream.ts +41 -0
- package/src/dogwood/window.ts +124 -0
- package/src/index.ts +76 -0
- package/src/lint/audit-catalog.ts +64 -0
- package/src/lint/post-synth/dogwood-helpers.ts +139 -0
- package/src/lint/post-synth/dwd-post-synth.test.ts +374 -0
- package/src/lint/post-synth/dwdc010.ts +62 -0
- package/src/lint/post-synth/dwdc011.ts +61 -0
- package/src/lint/post-synth/dwdc012.ts +46 -0
- package/src/lint/post-synth/dwdc013.ts +64 -0
- package/src/lint/post-synth/dwde-post-synth.test.ts +368 -0
- package/src/lint/post-synth/dwde010.ts +130 -0
- package/src/lint/post-synth/dwde011.ts +108 -0
- package/src/lint/post-synth/dwds010.ts +46 -0
- package/src/lint/post-synth/index.ts +14 -0
- package/src/lint/post-synth/post-synth.test.ts +7 -3
- package/src/op/activities/index.ts +27 -0
- package/src/plugin.test.ts +3 -2
- package/src/plugin.ts +30 -0
- package/src/policy-text.ts +128 -0
- package/src/serializer.ts +71 -109
- package/src/skills/chant-cedar-dogwood.md +327 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dogwood entity model: a temporal policy, an event schema, a macro library.
|
|
3
|
+
*
|
|
4
|
+
* `Dogwood::TemporalPolicy` is `Cedar::Policy` plus the two clause forms
|
|
5
|
+
* upstream's policy grammar adds. Its head — annotations, effect, the three
|
|
6
|
+
* scope positions — is Cedar's, byte for byte, which is why `./serialize.ts`
|
|
7
|
+
* renders it with the cedar serializer's own `renderPolicyHead` rather than a
|
|
8
|
+
* copy of it. Only the `cond` rule differs:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* cond = { cond_kw ~ (extension_marker | guardrails_tag? ~ "{" ~ expr ~ "}") }
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* — so a clause is `when { … }`, `when guardrails { … }`, or
|
|
15
|
+
* `when temporal { … }`, and the same three under `unless`. `guardrails` is
|
|
16
|
+
* transparent sugar for a bare Cedar expression (upstream discards the tag
|
|
17
|
+
* during lowering); `temporal { … }` is a genuine sub-language dispatched to a
|
|
18
|
+
* different parser.
|
|
19
|
+
*
|
|
20
|
+
* These are not schema-driven the way `Cedar::Policy`'s generated class is.
|
|
21
|
+
* Codegen's input is the project's `.cedarschema`, which says nothing about
|
|
22
|
+
* event kinds or temporal operators, so the dialect's classes are written here
|
|
23
|
+
* and typed against the builders in `./temporal.ts`.
|
|
24
|
+
*/
|
|
25
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
26
|
+
import type { CedarEffect, CedarScope } from "../serializer.js";
|
|
27
|
+
import type { TemporalCondition } from "./temporal.js";
|
|
28
|
+
import type { EventSchema } from "./event-schema.js";
|
|
29
|
+
import type { MacroDefinition } from "./macros.js";
|
|
30
|
+
/** The lexicon these entities belong to — dogwood is a dialect of cedar, not a lexicon. */
|
|
31
|
+
export declare const DOGWOOD_LEXICON = "cedar";
|
|
32
|
+
/** The `entityType` of a temporal policy. */
|
|
33
|
+
export declare const DOGWOOD_POLICY_TYPE = "Dogwood::TemporalPolicy";
|
|
34
|
+
/** The `entityType` of an event schema. */
|
|
35
|
+
export declare const DOGWOOD_EVENT_SCHEMA_TYPE = "Dogwood::EventSchema";
|
|
36
|
+
/** The `entityType` of a macro library. */
|
|
37
|
+
export declare const DOGWOOD_MACRO_LIBRARY_TYPE = "Dogwood::MacroLibrary";
|
|
38
|
+
/** The `.dw` policy set written beside the cedar outputs. */
|
|
39
|
+
export declare const DOGWOOD_POLICY_FILENAME = "policies.dw";
|
|
40
|
+
/** The `.dwschema` event schema — what `dogwood validate --event-schema` reads. */
|
|
41
|
+
export declare const DOGWOOD_EVENT_SCHEMA_FILENAME = "events.dwschema";
|
|
42
|
+
/** The macro library — what `dogwood validate --macros` reads. */
|
|
43
|
+
export declare const DOGWOOD_MACRO_FILENAME = "macros.dw";
|
|
44
|
+
/**
|
|
45
|
+
* The props of a `Dogwood::TemporalPolicy`.
|
|
46
|
+
*
|
|
47
|
+
* The first six mirror `CedarPolicyProps` exactly. The rest are the dialect's.
|
|
48
|
+
*/
|
|
49
|
+
export interface TemporalPolicyProps {
|
|
50
|
+
/** Defaults to `permit` when omitted. */
|
|
51
|
+
effect?: CedarEffect;
|
|
52
|
+
/** Defaults to unconstrained (`{}`) when omitted. */
|
|
53
|
+
principal?: CedarScope;
|
|
54
|
+
/** Defaults to unconstrained (`{}`) when omitted. */
|
|
55
|
+
action?: CedarScope;
|
|
56
|
+
/** Defaults to unconstrained (`{}`) when omitted. */
|
|
57
|
+
resource?: CedarScope;
|
|
58
|
+
/** Cedar expression strings, each emitted as its own `when { … }` clause. */
|
|
59
|
+
when?: string[];
|
|
60
|
+
/** Cedar expression strings, each emitted as its own `unless { … }` clause. */
|
|
61
|
+
unless?: string[];
|
|
62
|
+
/** Emitted as `@key("value")`; an explicit `id` wins over the logical name. */
|
|
63
|
+
annotations?: Record<string, string>;
|
|
64
|
+
/** Each emitted as its own `when temporal { … }` clause. */
|
|
65
|
+
whenTemporal?: TemporalCondition[];
|
|
66
|
+
/** Each emitted as its own `unless temporal { … }` clause. */
|
|
67
|
+
unlessTemporal?: TemporalCondition[];
|
|
68
|
+
/**
|
|
69
|
+
* Cedar expression strings emitted as `when guardrails { … }`.
|
|
70
|
+
*
|
|
71
|
+
* The tag carries no separate grammar — upstream parses the body as an
|
|
72
|
+
* ordinary Cedar expression and discards the tag when lowering. It marks a
|
|
73
|
+
* clause as a guardrail for a human reader and for whatever reads the source
|
|
74
|
+
* after chant; it does not change what the policy means.
|
|
75
|
+
*/
|
|
76
|
+
whenGuardrails?: string[];
|
|
77
|
+
/** As {@link whenGuardrails}, negated. */
|
|
78
|
+
unlessGuardrails?: string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A temporal policy. Declare one per policy, the same way as `Cedar::Policy`:
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* export const readAfterLogin = new TemporalPolicy({
|
|
85
|
+
* action: { eq: 'Drupe::Action::"Read"' },
|
|
86
|
+
* whenTemporal: [
|
|
87
|
+
* formerly("1h", predicate('Drupe::Action::"Login"', "response", {
|
|
88
|
+
* "input.user": ctx("input.user"),
|
|
89
|
+
* })),
|
|
90
|
+
* ],
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare const TemporalPolicy: new (props: TemporalPolicyProps) => Declarable;
|
|
95
|
+
/** The props of a `Dogwood::EventSchema`. */
|
|
96
|
+
export interface EventSchemaProps {
|
|
97
|
+
/** Built with `eventSchema()` or `defaultEventSchema()`. */
|
|
98
|
+
schema: EventSchema;
|
|
99
|
+
/** Defaults to {@link DOGWOOD_EVENT_SCHEMA_FILENAME}. */
|
|
100
|
+
filename?: string;
|
|
101
|
+
}
|
|
102
|
+
/** The service half of the schema, emitted as `.dwschema` text. */
|
|
103
|
+
export declare const TemporalEventSchema: new (props: EventSchemaProps) => Declarable;
|
|
104
|
+
/** The props of a `Dogwood::MacroLibrary`. */
|
|
105
|
+
export interface MacroLibraryProps {
|
|
106
|
+
macros: MacroDefinition[];
|
|
107
|
+
/** Defaults to {@link DOGWOOD_MACRO_FILENAME}. Ignored when `inline` is set. */
|
|
108
|
+
filename?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Emit the definitions at the top of the policy set instead of into their own
|
|
111
|
+
* file.
|
|
112
|
+
*
|
|
113
|
+
* A policy set's own `def` shadows a same-named library macro, so inlining is
|
|
114
|
+
* how a project stops depending on whoever runs the CLI passing `--macros`.
|
|
115
|
+
*/
|
|
116
|
+
inline?: boolean;
|
|
117
|
+
}
|
|
118
|
+
/** A `def cedar` / `def temporal` library, emitted as `.dw` text. */
|
|
119
|
+
export declare const TemporalMacroLibrary: new (props: MacroLibraryProps) => Declarable;
|
|
120
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/dogwood/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,4BAA4B,CAAC;AAE7D,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,2CAA2C;AAC3C,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAElE,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,gBAAgB,CAAC;AAErD,mFAAmF;AACnF,eAAO,MAAM,6BAA6B,oBAAoB,CAAC;AAE/D,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,qDAAqD;IACrD,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,qDAAqD;IACrD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,8DAA8D;IAC9D,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACrC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,EAA0E,KACnG,KAAK,EAAE,mBAAmB,KACvB,UAAU,CAAC;AAEhB,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,MAAM,EAAE,WAAW,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,EAAgF,KAC9G,KAAK,EAAE,gBAAgB,KACpB,UAAU,CAAC;AAEhB,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,EAAiF,KAChH,KAAK,EAAE,iBAAiB,KACrB,UAAU,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dogwoodReplay` / `dogwoodReplayReport` — the replay half of PolicyReplayOp
|
|
3
|
+
* (#1661, epic #1646).
|
|
4
|
+
*
|
|
5
|
+
* Contributed the way the fly lexicon contributes `flyApply`: a plain exported
|
|
6
|
+
* async function taking one args object, re-exported from
|
|
7
|
+
* `src/op/activities/index.ts`, resolved **by name** by core's activity
|
|
8
|
+
* registry when a project lists the `cedar` lexicon. There is no Temporal
|
|
9
|
+
* import here and no Temporal dependency in the package — the local executor
|
|
10
|
+
* runs it as-is, and a Temporal worker registers the same function.
|
|
11
|
+
*
|
|
12
|
+
* What it does: takes a policy bundle (inline text or paths), an event trace
|
|
13
|
+
* (typed events, inline text, or a path) and a set of expectations, runs
|
|
14
|
+
* `dogwood replay --format json` through the existing CLI adapter in
|
|
15
|
+
* `./cli.ts`, and returns a typed divergence report — expected versus actual
|
|
16
|
+
* verdict per decision point, with the determining rules and per-evaluation
|
|
17
|
+
* errors carried through.
|
|
18
|
+
*
|
|
19
|
+
* Three contract details from the #1657 verification shape the code:
|
|
20
|
+
*
|
|
21
|
+
* - **Replay exits 0 even when every verdict is DENY.** A nonzero exit means
|
|
22
|
+
* the trace or the policy set failed to load. `./cli.ts` already refuses to
|
|
23
|
+
* read exit codes as verdicts; this module refuses to read a DENY as a
|
|
24
|
+
* failure.
|
|
25
|
+
* - **A run that could not happen is not a run that found nothing.** An
|
|
26
|
+
* unusable invocation or a fatal (a malformed trace line, an unparseable
|
|
27
|
+
* policy set) throws, so the step fails instead of reporting zero
|
|
28
|
+
* divergences.
|
|
29
|
+
* - **`index` is the decision-stream position, not the trace line number.** A
|
|
30
|
+
* history-only event contributes history and no verdict, so expectations
|
|
31
|
+
* written against trace lines would silently address the wrong decision.
|
|
32
|
+
* Expectations therefore match on `timestamp` by default, and on `index`
|
|
33
|
+
* only when the caller says so.
|
|
34
|
+
*
|
|
35
|
+
* The trace input is deliberately generic. An AgentCore session/decision
|
|
36
|
+
* history is the follow-on source (it needs the aws lexicon's activity
|
|
37
|
+
* surface, out of scope here) — a trace is a trace, wherever it came from.
|
|
38
|
+
*/
|
|
39
|
+
import { type DogwoodBundle, type DogwoodVerdict } from "./cli.js";
|
|
40
|
+
import { type TraceEvent, type TraceIssue } from "./trace.js";
|
|
41
|
+
/** What a replay produces on divergence, mirroring `WorkflowAuditOp`'s modes. */
|
|
42
|
+
export type PolicyReplayMode = "report" | "issue" | "pull-request";
|
|
43
|
+
/** A verdict a decision point is expected to reach. */
|
|
44
|
+
export type ExpectedVerdict = "allow" | "deny";
|
|
45
|
+
/**
|
|
46
|
+
* One expectation against the decision stream.
|
|
47
|
+
*
|
|
48
|
+
* Give a `timestamp` (the `@<n>` of the line) or an `index` (the 0-based
|
|
49
|
+
* position in the decision stream). Prefer `timestamp`: it survives a trace
|
|
50
|
+
* gaining a history-only event, which shifts every later index.
|
|
51
|
+
*/
|
|
52
|
+
export interface ReplayExpectation {
|
|
53
|
+
readonly timestamp?: number;
|
|
54
|
+
readonly index?: number;
|
|
55
|
+
readonly verdict: ExpectedVerdict;
|
|
56
|
+
/** When set, the `.dw` rule indices the decision must be determined by. */
|
|
57
|
+
readonly determiningRules?: readonly number[];
|
|
58
|
+
/** What this decision point is proving, carried into the report. */
|
|
59
|
+
readonly note?: string;
|
|
60
|
+
}
|
|
61
|
+
/** One expected-versus-actual mismatch. */
|
|
62
|
+
export interface ReplayDivergence {
|
|
63
|
+
/** Decision-stream index. `-1` when the expected decision point never occurred. */
|
|
64
|
+
readonly index: number;
|
|
65
|
+
readonly timestamp: number;
|
|
66
|
+
/** Absent when the replay produced a decision nothing expected. */
|
|
67
|
+
readonly expected?: ExpectedVerdict;
|
|
68
|
+
/** Absent when an expected decision point produced no verdict at all. */
|
|
69
|
+
readonly actual?: ExpectedVerdict;
|
|
70
|
+
readonly determiningRules: readonly number[];
|
|
71
|
+
readonly errors: readonly string[];
|
|
72
|
+
readonly detail: string;
|
|
73
|
+
readonly note?: string;
|
|
74
|
+
}
|
|
75
|
+
/** What `dogwoodReplay` returns and `dogwoodReplayReport` reads back. */
|
|
76
|
+
export interface PolicyReplayReport {
|
|
77
|
+
/** True when nothing diverged and no decision point errored. */
|
|
78
|
+
readonly ok: boolean;
|
|
79
|
+
readonly mode: PolicyReplayMode;
|
|
80
|
+
/** Every decision point, in stream order. */
|
|
81
|
+
readonly verdicts: readonly DogwoodVerdict[];
|
|
82
|
+
readonly divergences: readonly ReplayDivergence[];
|
|
83
|
+
/** Divergence count — the number a search attribute or a gate reads. */
|
|
84
|
+
readonly findings: number;
|
|
85
|
+
/** Trace weaknesses found by `auditTrace`, when typed events were supplied. */
|
|
86
|
+
readonly traceIssues: readonly TraceIssue[];
|
|
87
|
+
/** Markdown, used as the report body or an issue/PR body. */
|
|
88
|
+
readonly summary: string;
|
|
89
|
+
}
|
|
90
|
+
/** What `dogwoodReplay` takes. Every artifact is inline text or a path. */
|
|
91
|
+
export interface DogwoodReplayArgs {
|
|
92
|
+
/** `.dw` policy set text. */
|
|
93
|
+
policies?: string;
|
|
94
|
+
/** …or a path to it. Relative paths resolve against {@link cwd}. */
|
|
95
|
+
policiesPath?: string;
|
|
96
|
+
/** Cedar action schema text (`--policy-schema`). Not optional to the CLI. */
|
|
97
|
+
policySchema?: string;
|
|
98
|
+
policySchemaPath?: string;
|
|
99
|
+
/** `.dwschema` event schema text (`--event-schema`). */
|
|
100
|
+
eventSchema?: string;
|
|
101
|
+
eventSchemaPath?: string;
|
|
102
|
+
/** `.dw` macro library text (`--macros`). */
|
|
103
|
+
macros?: string;
|
|
104
|
+
macrosPath?: string;
|
|
105
|
+
/** `providers.json` text (`--providers`). Rhai must be inlined under `implementation.script`. */
|
|
106
|
+
providers?: string;
|
|
107
|
+
providersPath?: string;
|
|
108
|
+
/** Typed events — rendered here, and audited for the both-bags trap. */
|
|
109
|
+
traceEvents?: readonly TraceEvent[];
|
|
110
|
+
/** …or the trace text as it would appear in a `.log`. */
|
|
111
|
+
trace?: string;
|
|
112
|
+
/** …or a path to it. */
|
|
113
|
+
tracePath?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Event kinds that decide, for the trace audit. Default `["request"]` — the
|
|
116
|
+
* truth is whichever kinds the `.dwschema` marks `decision`.
|
|
117
|
+
*/
|
|
118
|
+
traceDecisionKinds?: readonly string[];
|
|
119
|
+
/** What each decision point must decide. An empty list replays and reports. */
|
|
120
|
+
expect?: readonly ReplayExpectation[];
|
|
121
|
+
/** Default `report`. */
|
|
122
|
+
mode?: PolicyReplayMode;
|
|
123
|
+
/** Explicit binary path. Otherwise resolved by {@link findDogwoodBinary}. */
|
|
124
|
+
binary?: string;
|
|
125
|
+
/** Base directory for every relative path. Default `process.cwd()`. */
|
|
126
|
+
cwd?: string;
|
|
127
|
+
/** When set, the report is written here as JSON for the Report phase to read. */
|
|
128
|
+
reportPath?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Assemble the bundle and the trace from whichever form the caller supplied.
|
|
132
|
+
*
|
|
133
|
+
* Exported because the composite's Artifacts phase writes files and the Replay
|
|
134
|
+
* phase names them: resolving the same way in a test as in the Op is the point
|
|
135
|
+
* of having one function do it.
|
|
136
|
+
*/
|
|
137
|
+
export declare function resolveReplayInputs(args: DogwoodReplayArgs): Promise<{
|
|
138
|
+
bundle: DogwoodBundle;
|
|
139
|
+
trace: string;
|
|
140
|
+
traceIssues: TraceIssue[];
|
|
141
|
+
}>;
|
|
142
|
+
/**
|
|
143
|
+
* Match expectations against the decision stream.
|
|
144
|
+
*
|
|
145
|
+
* Timestamp matching consumes verdicts left to right, so two expectations at
|
|
146
|
+
* the same `@n` address the first and second decision there rather than both
|
|
147
|
+
* addressing the first. A verdict nothing expected is reported too — a policy
|
|
148
|
+
* set that starts deciding somewhere new is drift, and the usual reason a
|
|
149
|
+
* replay is being run at all.
|
|
150
|
+
*/
|
|
151
|
+
export declare function compareVerdicts(verdicts: readonly DogwoodVerdict[], expectations: readonly ReplayExpectation[]): ReplayDivergence[];
|
|
152
|
+
/** The markdown body — printed in `report` mode, posted in the other two. */
|
|
153
|
+
export declare function renderReplaySummary(report: Omit<PolicyReplayReport, "summary">): string;
|
|
154
|
+
/**
|
|
155
|
+
* Replay a policy bundle against a trace and report divergence.
|
|
156
|
+
*
|
|
157
|
+
* Throws when the CLI could not be used or the run was fatal. That is the
|
|
158
|
+
* distinction `./cli.ts` draws and this preserves: a replay that did not
|
|
159
|
+
* happen must fail the step, never report zero divergences.
|
|
160
|
+
*/
|
|
161
|
+
export declare function dogwoodReplay(args: DogwoodReplayArgs): Promise<PolicyReplayReport>;
|
|
162
|
+
/** What `dogwoodReplayReport` takes. */
|
|
163
|
+
export interface DogwoodReplayReportArgs {
|
|
164
|
+
/** The JSON `dogwoodReplay` wrote. Relative paths resolve against {@link cwd}. */
|
|
165
|
+
reportPath?: string;
|
|
166
|
+
/** …or the report itself, for a caller holding it already. */
|
|
167
|
+
report?: PolicyReplayReport;
|
|
168
|
+
/** Overrides the mode recorded in the report. */
|
|
169
|
+
mode?: PolicyReplayMode;
|
|
170
|
+
/** Title for the issue or pull request. */
|
|
171
|
+
title?: string;
|
|
172
|
+
cwd?: string;
|
|
173
|
+
/** Fail the step when the replay diverged. Default false — the mode decides. */
|
|
174
|
+
failOnDivergence?: boolean;
|
|
175
|
+
}
|
|
176
|
+
/** What the Report phase produces. */
|
|
177
|
+
export interface PolicyReplayDispatch {
|
|
178
|
+
readonly mode: PolicyReplayMode;
|
|
179
|
+
readonly findings: number;
|
|
180
|
+
readonly title: string;
|
|
181
|
+
/** The markdown to print, or to use as an issue/PR body. */
|
|
182
|
+
readonly body: string;
|
|
183
|
+
/** True when there is something to say — an issue/PR is only worth opening then. */
|
|
184
|
+
readonly actionable: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Turn a written replay report into the thing the finding mode calls for.
|
|
188
|
+
*
|
|
189
|
+
* It renders and returns; it does not open anything. Same as
|
|
190
|
+
* `workflowSupplyChainAudit`, and for the same reason — the cedar lexicon has
|
|
191
|
+
* no forge client and should not grow one to reach GitHub, GitLab or Forgejo.
|
|
192
|
+
* `report` mode prints the body; `issue` and `pull-request` hand back the
|
|
193
|
+
* title and body for whatever step opens them.
|
|
194
|
+
*/
|
|
195
|
+
export declare function dogwoodReplayReport(args: DogwoodReplayReportArgs): Promise<PolicyReplayDispatch>;
|
|
196
|
+
//# sourceMappingURL=replay-activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-activity.d.ts","sourceRoot":"","sources":["../../src/dogwood/replay-activity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `PolicyReplayOp` — replay a declared `.dw` set against a recorded event
|
|
3
|
+
* trace and report divergence (#1661, epic #1646).
|
|
4
|
+
*
|
|
5
|
+
* Shape follows `WorkflowAuditOp`: an observe-dial Op whose last phase is a
|
|
6
|
+
* finding mode (`report | issue | pull-request`). What it observes is not a
|
|
7
|
+
* moving upstream but a moving *history* — a policy set that was correct
|
|
8
|
+
* against last week's traffic can decide differently against this week's, and
|
|
9
|
+
* the deterministic build cannot see that.
|
|
10
|
+
*
|
|
11
|
+
* ## Packaging: the composite ships from cedar, not from temporal
|
|
12
|
+
*
|
|
13
|
+
* `WorkflowAuditOp` and `PipelineAuditOp` live in the temporal lexicon because
|
|
14
|
+
* they hand back a `TemporalSchedule` alongside the Op, and that resource is
|
|
15
|
+
* temporal's. This composite hands back an Op and nothing else, so it has no
|
|
16
|
+
* reason to reach across — it imports `@intentius/chant/op` only, exactly as
|
|
17
|
+
* the fly lexicon's `flyDeploy` composite does. cedar therefore keeps zero
|
|
18
|
+
* runtime dependency on `@intentius/chant-lexicon-temporal`.
|
|
19
|
+
*
|
|
20
|
+
* The scheduled form is a two-line project-side pairing rather than a config
|
|
21
|
+
* flag, and that is the deliberate cost of the decision:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { TemporalSchedule } from "@intentius/chant-lexicon-temporal";
|
|
25
|
+
*
|
|
26
|
+
* export const { op } = PolicyReplayOp({ name: "policy-replay", … });
|
|
27
|
+
* export const schedule = new TemporalSchedule({
|
|
28
|
+
* scheduleId: "policy-replay-schedule",
|
|
29
|
+
* spec: { cronExpressions: ["0 6 * * *"] },
|
|
30
|
+
* action: { workflowType: "policyReplayWorkflow", taskQueue: "policy-replay" },
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* A project that wants that already installs the temporal lexicon; a project
|
|
35
|
+
* that only wants `chant run policy-replay` on the local executor should not
|
|
36
|
+
* have to. `examples/policy-replay` is the worked recipe for both.
|
|
37
|
+
*
|
|
38
|
+
* ## Phases
|
|
39
|
+
*
|
|
40
|
+
* ```
|
|
41
|
+
* Artifacts chantBuild — emit policies.dw, the .cedarschema and the
|
|
42
|
+
* .dwschema the replay reads (skippable when they are checked in)
|
|
43
|
+
* Replay dogwoodReplay — run `dogwood replay --format json` over the
|
|
44
|
+
* bundle and the trace, write the divergence report
|
|
45
|
+
* Report dogwoodReplayReport — read that report and act on the mode
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* The report file is the seam between the last two phases, the same way
|
|
49
|
+
* `dist/fly.json` is the seam between `build:fly` and `flyApply`: Op steps do
|
|
50
|
+
* not pass return values to one another, so a phase boundary needs an artifact
|
|
51
|
+
* to be a real boundary rather than a cosmetic one.
|
|
52
|
+
*/
|
|
53
|
+
import { type ActivityStep, type OpResource } from "@intentius/chant/op";
|
|
54
|
+
import type { PolicyReplayMode, ReplayExpectation } from "./replay-activity.js";
|
|
55
|
+
/** Where the Replay phase writes its report by default. */
|
|
56
|
+
export declare const DEFAULT_REPLAY_REPORT_PATH = "dist/dogwood-replay.json";
|
|
57
|
+
/** Options for {@link dogwoodReplayStep}. Mirrors `DogwoodReplayArgs`. */
|
|
58
|
+
export interface DogwoodReplayStepOpts {
|
|
59
|
+
policies?: string;
|
|
60
|
+
policiesPath?: string;
|
|
61
|
+
policySchema?: string;
|
|
62
|
+
policySchemaPath?: string;
|
|
63
|
+
eventSchema?: string;
|
|
64
|
+
eventSchemaPath?: string;
|
|
65
|
+
macros?: string;
|
|
66
|
+
macrosPath?: string;
|
|
67
|
+
providers?: string;
|
|
68
|
+
providersPath?: string;
|
|
69
|
+
trace?: string;
|
|
70
|
+
tracePath?: string;
|
|
71
|
+
expect?: readonly ReplayExpectation[];
|
|
72
|
+
mode?: PolicyReplayMode;
|
|
73
|
+
binary?: string;
|
|
74
|
+
cwd?: string;
|
|
75
|
+
reportPath?: string;
|
|
76
|
+
profile?: ActivityStep["profile"];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Replay a policy bundle against a trace — the typed twin of `flyApplyStep`.
|
|
80
|
+
*
|
|
81
|
+
* Resolves to the `dogwoodReplay` activity by name, which `loadActivities`
|
|
82
|
+
* binds when the project lists the `cedar` lexicon. Defaults to the
|
|
83
|
+
* `policyCheck` profile.
|
|
84
|
+
*/
|
|
85
|
+
export declare const dogwoodReplayStep: (opts: DogwoodReplayStepOpts) => ActivityStep;
|
|
86
|
+
/** Options for {@link dogwoodReplayReportStep}. */
|
|
87
|
+
export interface DogwoodReplayReportStepOpts {
|
|
88
|
+
reportPath?: string;
|
|
89
|
+
mode?: PolicyReplayMode;
|
|
90
|
+
title?: string;
|
|
91
|
+
cwd?: string;
|
|
92
|
+
failOnDivergence?: boolean;
|
|
93
|
+
profile?: ActivityStep["profile"];
|
|
94
|
+
}
|
|
95
|
+
/** Read a written replay report and act on its finding mode. */
|
|
96
|
+
export declare const dogwoodReplayReportStep: (opts?: DogwoodReplayReportStepOpts) => ActivityStep;
|
|
97
|
+
/** Options for {@link PolicyReplayOp}. */
|
|
98
|
+
export interface PolicyReplayOpConfig {
|
|
99
|
+
/** Op name (kebab-case) — the `chant run <name>` target and the task queue base. */
|
|
100
|
+
name: string;
|
|
101
|
+
overview?: string;
|
|
102
|
+
/** Defaults to {@link name}. */
|
|
103
|
+
taskQueue?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Directory every relative path below resolves against, and the one the
|
|
106
|
+
* build script runs in. Default `.`.
|
|
107
|
+
*/
|
|
108
|
+
path?: string;
|
|
109
|
+
/**
|
|
110
|
+
* npm script that emits the `.dw` bundle. Default `build`. Pass `false` when
|
|
111
|
+
* the artifacts are checked in — the Artifacts phase is then omitted rather
|
|
112
|
+
* than run as a no-op, so the Op's phase list says what it really does.
|
|
113
|
+
*/
|
|
114
|
+
buildScript?: string | false;
|
|
115
|
+
/** Emitted `.dw` policy set. Default `dist/policies.dw`. */
|
|
116
|
+
policiesPath?: string;
|
|
117
|
+
/** Emitted Cedar action schema. Required by the CLI; default `dist/app.cedarschema`. */
|
|
118
|
+
policySchemaPath?: string;
|
|
119
|
+
/** Emitted `.dwschema`, when the project declares one. */
|
|
120
|
+
eventSchemaPath?: string;
|
|
121
|
+
/** Emitted macro library, when the project ships one out of line. */
|
|
122
|
+
macrosPath?: string;
|
|
123
|
+
/** `providers.json`, with the Rhai inlined under `implementation.script`. */
|
|
124
|
+
providersPath?: string;
|
|
125
|
+
/** The recorded trace to replay. Required — there is nothing to replay without one. */
|
|
126
|
+
tracePath: string;
|
|
127
|
+
/** What each decision point must decide. Empty replays and reports verdicts. */
|
|
128
|
+
expect?: readonly ReplayExpectation[];
|
|
129
|
+
/** What to produce on divergence. Default `report`. */
|
|
130
|
+
onFinding?: PolicyReplayMode;
|
|
131
|
+
/** Title for the issue or pull request the finding mode calls for. */
|
|
132
|
+
title?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Fail the Op when the replay diverged. Default false — an observe-dial Op
|
|
135
|
+
* reports by default, and a red run is a decision the caller makes.
|
|
136
|
+
*/
|
|
137
|
+
failOnDivergence?: boolean;
|
|
138
|
+
/** Where the Replay phase writes its report. Default {@link DEFAULT_REPLAY_REPORT_PATH}. */
|
|
139
|
+
reportPath?: string;
|
|
140
|
+
/** Explicit `dogwood` binary path, for a runner that knows where it built one. */
|
|
141
|
+
binary?: string;
|
|
142
|
+
}
|
|
143
|
+
/** What {@link PolicyReplayOp} hands back. */
|
|
144
|
+
export interface PolicyReplayOpResources {
|
|
145
|
+
/** The Op — discovered by `chant run <name>`, emitted by `chant build`. */
|
|
146
|
+
op: InstanceType<typeof OpResource>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Assemble the replay Op: emit the artifacts, replay them, act on the finding.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* export const { op } = PolicyReplayOp({
|
|
154
|
+
* name: "policy-replay",
|
|
155
|
+
* tracePath: "trace/read-after-login.log",
|
|
156
|
+
* expect: [
|
|
157
|
+
* { timestamp: 10, verdict: "allow", determiningRules: [0] },
|
|
158
|
+
* { timestamp: 7200, verdict: "deny", note: "the login is two hours stale" },
|
|
159
|
+
* ],
|
|
160
|
+
* onFinding: "issue",
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export declare function PolicyReplayOp(config: PolicyReplayOpConfig): PolicyReplayOpResources;
|
|
165
|
+
//# sourceMappingURL=replay-op.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-op.d.ts","sourceRoot":"","sources":["../../src/dogwood/replay-op.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the emitted dogwood artifacts back, for the DWD post-synth checks.
|
|
3
|
+
*
|
|
4
|
+
* The checks judge the *text*, not the in-memory model, for the same reason
|
|
5
|
+
* the CED checks judge `policies.cedar.json`: `chant audit` runs over a
|
|
6
|
+
* checked-in artifact chant did not write, and a wall that only fires on
|
|
7
|
+
* chant's own output is not a wall. It also means the typed builders and the
|
|
8
|
+
* walls are independent — DWDC012 catches a windowless `formerly` even though
|
|
9
|
+
* the builders cannot construct one, because `raw()` and a hand-written `.dw`
|
|
10
|
+
* both can.
|
|
11
|
+
*
|
|
12
|
+
* This is scanning, not parsing. Upstream owns the parser and #1659 owns
|
|
13
|
+
* shelling to it; what is here is the subset of the surface that answers the
|
|
14
|
+
* three questions the walls ask, plus enough comment handling not to be fooled
|
|
15
|
+
* by a commented-out clause.
|
|
16
|
+
*/
|
|
17
|
+
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
18
|
+
/** One emitted artifact, with everything needed to name it in a finding. */
|
|
19
|
+
export interface DogwoodArtifact {
|
|
20
|
+
/** The lexicon output it came from. */
|
|
21
|
+
lexicon: string;
|
|
22
|
+
/** The filename, which is what a finding points the reader at. */
|
|
23
|
+
source: string;
|
|
24
|
+
/** The file's text. */
|
|
25
|
+
text: string;
|
|
26
|
+
}
|
|
27
|
+
/** Every `.dw` policy file in the build output. */
|
|
28
|
+
export declare function dogwoodPolicyFiles(ctx: PostSynthContext): DogwoodArtifact[];
|
|
29
|
+
/** Every `.dwschema` event-schema file in the build output. */
|
|
30
|
+
export declare function dogwoodSchemaFiles(ctx: PostSynthContext): DogwoodArtifact[];
|
|
31
|
+
/**
|
|
32
|
+
* Blank out `//` comments, leaving string literals intact.
|
|
33
|
+
*
|
|
34
|
+
* String literals stay because a predicate's action id lives inside one
|
|
35
|
+
* (`Drupe::Action::"Read"`), and blanking those would blind every scan below.
|
|
36
|
+
* The walk is string-aware in the other direction too: a `//` inside a quoted
|
|
37
|
+
* value (a URL, say) is not a comment.
|
|
38
|
+
*
|
|
39
|
+
* Comment bytes become spaces so every offset in the result still lines up
|
|
40
|
+
* with the original file.
|
|
41
|
+
*/
|
|
42
|
+
export declare function blankComments(text: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* The stretches of a `.dw` file that the temporal sub-parser reads: every
|
|
45
|
+
* `temporal { … }` marker body, and every `def temporal … { … }` macro body.
|
|
46
|
+
*
|
|
47
|
+
* Scanning only these is what keeps a Cedar `when { … }` clause from being
|
|
48
|
+
* mistaken for temporal source — `context.retryWindow == 3` should not read as
|
|
49
|
+
* a window, and a Cedar attribute named `since` is not the `since` operator.
|
|
50
|
+
*/
|
|
51
|
+
export declare function temporalRegions(text: string): string[];
|
|
52
|
+
/** One `Ns::Action::"Name"::kind` predicate head found in temporal source. */
|
|
53
|
+
export interface TemporalPredicateRef {
|
|
54
|
+
/** The qualified action, quoted id and all. */
|
|
55
|
+
action: string;
|
|
56
|
+
/** The event kind segment after the quoted id. */
|
|
57
|
+
kind: string;
|
|
58
|
+
}
|
|
59
|
+
/** Every temporal predicate head in a `.dw` file, in source order. */
|
|
60
|
+
export declare function scanPredicates(text: string): TemporalPredicateRef[];
|
|
61
|
+
/** One window literal found in temporal source. */
|
|
62
|
+
export interface WindowRef {
|
|
63
|
+
/** As written: `48h`. */
|
|
64
|
+
text: string;
|
|
65
|
+
seconds: number;
|
|
66
|
+
/** `within` for an operator's window, `argument` for a bare macro-call interval. */
|
|
67
|
+
position: "within" | "argument";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Every window literal in a `.dw` file's temporal source.
|
|
71
|
+
*
|
|
72
|
+
* Both shapes count against `max_window`: a macro-call interval is the window
|
|
73
|
+
* a `within ?w` in the macro body resolves to, so `once(48h, …)` looks back
|
|
74
|
+
* exactly as far as `formerly within 48h` does.
|
|
75
|
+
*/
|
|
76
|
+
export declare function scanWindows(text: string): WindowRef[];
|
|
77
|
+
/**
|
|
78
|
+
* Every `formerly` / `previous` / `since` that is not followed by a `within`.
|
|
79
|
+
*
|
|
80
|
+
* Unrepresentable through the builders — {@link formerly} and its siblings all
|
|
81
|
+
* take the window as an argument — but reachable through `raw()`, through a
|
|
82
|
+
* hand-written `.dw`, and through an audit of a file chant never wrote.
|
|
83
|
+
*/
|
|
84
|
+
export declare function scanWindowlessOperators(text: string): string[];
|
|
85
|
+
/** What a `.dwschema` file says, as far as the walls need to know. */
|
|
86
|
+
export interface EventSchemaFacts {
|
|
87
|
+
/** Every declared event kind. */
|
|
88
|
+
kinds: string[];
|
|
89
|
+
/** The `max_window` directive in seconds, or upstream's 24h default when absent. */
|
|
90
|
+
maxWindowSeconds: number;
|
|
91
|
+
/** As written (`30d`), or undefined when the directive is absent. */
|
|
92
|
+
maxWindowText?: string;
|
|
93
|
+
/** True when at least one field carries a `pin … = …`. */
|
|
94
|
+
hasPin: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** Read a `.dwschema` file's declarations. */
|
|
97
|
+
export declare function readEventSchema(text: string): EventSchemaFacts;
|
|
98
|
+
/**
|
|
99
|
+
* The look-back cap in force for a build.
|
|
100
|
+
*
|
|
101
|
+
* With no emitted schema, `ServiceSchema::defaults()` applies and the cap is
|
|
102
|
+
* 24h. With several, the tightest one wins — a window legal under one schema
|
|
103
|
+
* and not another is a window some consumer will reject.
|
|
104
|
+
*/
|
|
105
|
+
export declare function effectiveMaxWindowSeconds(schemas: EventSchemaFacts[]): {
|
|
106
|
+
seconds: number;
|
|
107
|
+
text: string;
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/dogwood/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIzE,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,eAAe,EAAE,CAE3E;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,eAAe,EAAE,CAE3E;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyBlD;AAID;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBtD;AAyBD,8EAA8E;AAC9E,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAID,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,EAAE,CASnE;AAED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAAC;CACjC;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAarD;AAOD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAU9D;AAID,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC;CACjB;AAMD,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAkB9D;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAaxG"}
|