@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
package/README.md
CHANGED
|
@@ -17,6 +17,11 @@ INTENTIUS/chant#1645: the upstream pin (#1648), the scaffold and serializer
|
|
|
17
17
|
import/reconcile (#1653), the docs/LSP/MCP/skills/composites surface (#1654),
|
|
18
18
|
and CI/publishing onboarding (#1655).
|
|
19
19
|
|
|
20
|
+
Landing beside it, and pre-release on its own terms, is the dogwood temporal
|
|
21
|
+
dialect (epic #1646) — see [The dogwood dialect](#the-dogwood-dialect-pre-release).
|
|
22
|
+
It is a surface *inside* this lexicon rather than a sibling, so the eight
|
|
23
|
+
sub-issues above are still the whole of Cedar itself.
|
|
24
|
+
|
|
20
25
|
## The policy model
|
|
21
26
|
|
|
22
27
|
A policy is a `Cedar::Policy` entity whose props are:
|
|
@@ -121,7 +126,8 @@ import { OwnerCanManage, DenyByDefaultSet } from "@intentius/chant-lexicon-cedar
|
|
|
121
126
|
|
|
122
127
|
## Agent surface
|
|
123
128
|
|
|
124
|
-
|
|
129
|
+
Four skills (`chant-cedar-authoring`, `chant-cedar-avp-embedding`,
|
|
130
|
+
`chant-cedar-meta-policy`, `chant-cedar-dogwood`),
|
|
125
131
|
three `chant init` templates (`default`, `avp-embedding`,
|
|
126
132
|
`gateway-policy-set`), and three MCP contributions:
|
|
127
133
|
|
|
@@ -159,6 +165,101 @@ policy. AVP policy stores are taggable and individual policies are not, so
|
|
|
159
165
|
chant's per-policy ownership marker rides in the policy description — the
|
|
160
166
|
design record is `src/avp/OWNERSHIP.md`.
|
|
161
167
|
|
|
168
|
+
## The dogwood dialect (pre-release)
|
|
169
|
+
|
|
170
|
+
[Dogwood](https://github.com/dogwood-policy/dogwood) is Cedar with temporal
|
|
171
|
+
operators: a policy can depend on what already happened in a session, so
|
|
172
|
+
approval-before-action, rate limits and budgets become policy rather than
|
|
173
|
+
application code. It ships here as a dialect rather than as a sibling lexicon —
|
|
174
|
+
a `.dw` file stripped of Cedar semantics is meaningless, and the head of a
|
|
175
|
+
`.dw` policy is Cedar's, byte for byte. Its checks are under the `DWD` id
|
|
176
|
+
family, declared on the serializer's `extraRulePrefixes`.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import { TemporalPolicy, TemporalEventSchema, dogwood } from "@intentius/chant-lexicon-cedar";
|
|
180
|
+
|
|
181
|
+
export const events = new TemporalEventSchema({ schema: dogwood.defaultEventSchema() });
|
|
182
|
+
|
|
183
|
+
export const readAfterLogin = new TemporalPolicy({
|
|
184
|
+
action: { eq: 'Drupe::Action::"Read"' },
|
|
185
|
+
whenTemporal: [
|
|
186
|
+
dogwood.formerly("1h", dogwood.predicate('Drupe::Action::"Login"', "response", {
|
|
187
|
+
"input.user": dogwood.ctx("input.user"),
|
|
188
|
+
})),
|
|
189
|
+
],
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
A build holding temporal policies emits `policies.dw` beside the `.cedar`
|
|
194
|
+
outputs, plus `events.dwschema` and `macros.dw` where those are declared.
|
|
195
|
+
|
|
196
|
+
The builders target dogwood's **parser primitives** — `formerly`, `previous`,
|
|
197
|
+
`since`, `exists`, `tp()`, `count for … where`, `sum … for … where` — because
|
|
198
|
+
those are the only temporal keywords in the grammar. `count_within`,
|
|
199
|
+
`sum_within` and `count_distinct_within` are macros in a default library that
|
|
200
|
+
a caller passing `--macros` replaces wholesale, so they are expressible as
|
|
201
|
+
calls (`dogwood.countWithin`) and never as operators. `dogwood.defaultMacroLibrary()`
|
|
202
|
+
emits the same definitions into a project's own file for anyone who would
|
|
203
|
+
rather not depend on the far end's.
|
|
204
|
+
|
|
205
|
+
Three walls run in the build with no dogwood binary anywhere: a temporal
|
|
206
|
+
predicate naming an event kind the emitted `.dwschema` never declares
|
|
207
|
+
(DWDC010), a window past the schema's `max_window` or upstream's 24h default
|
|
208
|
+
(DWDC011), and a `formerly`/`previous`/`since` with no window (DWDC012, which
|
|
209
|
+
the typed builders already make unrepresentable). DWDS010 reports an event
|
|
210
|
+
schema that pins nothing — supplying any schema opts out of upstream's
|
|
211
|
+
`callerPrincipal` pin, which widens every temporal predicate to cross-principal.
|
|
212
|
+
|
|
213
|
+
Pre-release. Upstream is a read-only squash-sync mirror of an internal Amazon
|
|
214
|
+
repository with no tags, no releases and no stability statement, and its README
|
|
215
|
+
says it is not intended for production use. The revision this is built against
|
|
216
|
+
is recorded in `src/dogwood/upstream.ts`; full `.dw` validation shells to the
|
|
217
|
+
`dogwood` binary and is deliberately not part of any gating check.
|
|
218
|
+
|
|
219
|
+
Five pages in the docs site cover the dialect, and the skill
|
|
220
|
+
`chant-cedar-dogwood` covers it for an agent:
|
|
221
|
+
|
|
222
|
+
| Page | What it answers |
|
|
223
|
+
|---|---|
|
|
224
|
+
| [The Dogwood Dialect](docs/src/content/docs/dogwood.mdx) | What ships, what pre-release means, how upstream is governed |
|
|
225
|
+
| [Temporal Policies](docs/src/content/docs/dogwood-temporal-policies.mdx) | The builders, the operators, and which of them are really macros |
|
|
226
|
+
| [Event Schemas](docs/src/content/docs/dogwood-event-schemas.mdx) | The `.dwschema` surface and the `callerPrincipal` pin |
|
|
227
|
+
| [Validation](docs/src/content/docs/dogwood-validation.mdx) | The DWD walls, the CLI-gated checks, and the binary knobs |
|
|
228
|
+
| [Replay](docs/src/content/docs/dogwood-replay.mdx) | Typed traces, `PolicyReplayOp`, and the both-bags trap |
|
|
229
|
+
|
|
230
|
+
## Bedrock AgentCore
|
|
231
|
+
|
|
232
|
+
`AWS::BedrockAgentCore::Policy` is where a temporal policy is actually
|
|
233
|
+
deployed, and its `Definition` is a two-arm `oneOf`: `Cedar.Statement` for plain
|
|
234
|
+
Cedar, `Policy.Statement` for anything else. That second arm is what a `.dw`
|
|
235
|
+
policy travels in.
|
|
236
|
+
|
|
237
|
+
`agentCorePolicyDefinition(name, policy)` picks the arm from the policy — a
|
|
238
|
+
`TemporalPolicy`, or any props carrying a temporal clause, goes to `Policy`;
|
|
239
|
+
plain Cedar goes to `Cedar`. Same no-dependency rule as the AVP seam above: the
|
|
240
|
+
seam is the data shape, not an import. Templates are refused, because
|
|
241
|
+
AgentCore's union has no template-linked arm.
|
|
242
|
+
|
|
243
|
+
`EnforcementMode` is the staging dial. `LOG_ONLY` is evaluated on every request
|
|
244
|
+
and its decision is observed rather than returned, which is observe-before-
|
|
245
|
+
enforce in the substrate, per policy — and it is how a temporal rule should
|
|
246
|
+
start, since whether `formerly within 1h …` fires depends on traffic nobody has
|
|
247
|
+
replayed:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
new BedrockAgentCorePolicy({
|
|
251
|
+
PolicyEngineId: engine.ref(),
|
|
252
|
+
...agentCoreStagedPolicy("writeNeedsApproval", writeNeedsApproval, "log-only"),
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Promotion is `"log-only"` → `"enforce"`. The resource carries a statement and
|
|
257
|
+
nothing else, so the event schema has no property to live in and is registered
|
|
258
|
+
with the engine separately; DWDC013 warns when a build embeds temporal text and
|
|
259
|
+
emits no `.dwschema` beside it, because the deployed statement then matches
|
|
260
|
+
nothing and fails open or closed without failing. See
|
|
261
|
+
`examples/agentcore-policy/`.
|
|
262
|
+
|
|
162
263
|
## Commands
|
|
163
264
|
|
|
164
265
|
```bash
|
|
@@ -175,7 +276,10 @@ npm run docs:build # build the Starlight site in docs/
|
|
|
175
276
|
|
|
176
277
|
- `src/plugin.ts` — LexiconPlugin with all lifecycle methods
|
|
177
278
|
- `src/serializer.ts` — `.cedar` text and JSON policy-set output
|
|
279
|
+
- `src/policy-text.ts` — policy-head rendering shared by every renderer
|
|
178
280
|
- `src/avp/` — AVP embedding, the policy-store readers, and the ownership channel
|
|
281
|
+
- `src/agentcore/` — the AgentCore `Definition` seam and the `EnforcementMode` dial
|
|
282
|
+
- `src/dogwood/` — the temporal dialect: builders, `.dw`/`.dwschema` output
|
|
179
283
|
- `src/import/` — `chant import` parser, generator and round-trip fixtures
|
|
180
284
|
- `src/detect.ts` — which documents belong to this lexicon
|
|
181
285
|
- `src/codegen/` — code generation, docs, and packaging pipelines
|
|
@@ -184,7 +288,7 @@ npm run docs:build # build the Starlight site in docs/
|
|
|
184
288
|
- `src/lsp/` — LSP completions and hover over the generated registry
|
|
185
289
|
- `src/mcp/` — MCP tools and resources, including policy coverage
|
|
186
290
|
- `src/composites/` — `OwnerCanManage`, `DenyByDefaultSet`
|
|
187
|
-
- `src/skills/` — the
|
|
291
|
+
- `src/skills/` — the four agent skills
|
|
188
292
|
- `src/init-templates.ts` — `chant init --lexicon cedar --template …`
|
|
189
293
|
- `src/generated/` — generated artifacts (do not edit)
|
|
190
294
|
- `docs/` — the standalone Starlight site, generated by `npm run docs`
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed embedding of a cedar or dogwood policy into
|
|
3
|
+
* `AWS::BedrockAgentCore::Policy` (#1660).
|
|
4
|
+
*
|
|
5
|
+
* The aws lexicon keeps the deployment vehicle, exactly as it does for AVP
|
|
6
|
+
* (#1652, `../avp/embed.ts`). What differs is the shape of the vehicle:
|
|
7
|
+
* AgentCore's `Definition` is a two-arm `oneOf`, not the single `Static` arm
|
|
8
|
+
* `AWS::VerifiedPermissions::Policy` has —
|
|
9
|
+
*
|
|
10
|
+
* ```jsonc
|
|
11
|
+
* "PolicyDefinition": {
|
|
12
|
+
* "oneOf": [{ "required": ["Cedar"] }, { "required": ["Policy"] }]
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* — where `Cedar.Statement` is plain Cedar and `Policy.Statement` is the
|
|
17
|
+
* language-agnostic arm. That second arm is what makes AgentCore the
|
|
18
|
+
* deployment target for the dogwood dialect: a `.dw` policy is a Cedar policy
|
|
19
|
+
* with `when temporal { … }` clauses, which the `Cedar` arm has no business
|
|
20
|
+
* accepting, and the `Policy` arm exists precisely so a policy engine can be
|
|
21
|
+
* handed something that is not plain Cedar.
|
|
22
|
+
*
|
|
23
|
+
* A project that has both lexicons installed writes
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* new BedrockAgentCorePolicy({
|
|
27
|
+
* PolicyEngineId: engine.ref(),
|
|
28
|
+
* Name: "writeNeedsApproval",
|
|
29
|
+
* ...agentCoreStagedPolicy("writeNeedsApproval", writeNeedsApproval, "log-only"),
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* and the statement is the same text `chant build` writes to `policies.dw`,
|
|
34
|
+
* rendered by the same renderer, with `@id` intact.
|
|
35
|
+
*
|
|
36
|
+
* ### Why no dependency, and why the example uses plain objects
|
|
37
|
+
*
|
|
38
|
+
* Same rule as `../avp/embed.ts` and for the same reason: a cedar → aws
|
|
39
|
+
* dependency would invert the epic's decision that Cedar is vendor-neutral and
|
|
40
|
+
* make the cedar lexicon unbuildable without the aws one. Nothing here imports
|
|
41
|
+
* `@intentius/chant-lexicon-aws`. The seam is the data shape, which is stable
|
|
42
|
+
* CloudFormation, and the prop names below are the generated class's own
|
|
43
|
+
* (`PolicyEngineId`, `Name`, `Definition`, `EnforcementMode`, `Description`),
|
|
44
|
+
* so substituting the real class is a one-line edit. `examples/agentcore-policy/`
|
|
45
|
+
* demonstrates the pairing with a plain-object stand-in, because the shipped
|
|
46
|
+
* cedar examples build against the cedar serializer alone and an `AWS::*` entity
|
|
47
|
+
* declared in that tree would have no serializer to emit it.
|
|
48
|
+
*
|
|
49
|
+
* ### What this module refuses
|
|
50
|
+
*
|
|
51
|
+
* Templates. `AWS::VerifiedPermissions::Policy` has a `TemplateLinked` arm;
|
|
52
|
+
* AgentCore's `Definition` union does not, so a statement carrying a
|
|
53
|
+
* `?principal` or `?resource` slot has nowhere to go and would be rejected at
|
|
54
|
+
* deploy time with an error about the policy text rather than about the slot.
|
|
55
|
+
* {@link agentCoreStatement} throws instead, at authoring time, naming the
|
|
56
|
+
* declaration.
|
|
57
|
+
*/
|
|
58
|
+
import { type Declarable } from "@intentius/chant/declarable";
|
|
59
|
+
import { type CedarPolicyProps } from "../serializer.js";
|
|
60
|
+
import { type TemporalPolicyProps } from "../dogwood/policy.js";
|
|
61
|
+
import { type AgentCoreEnforcementMode, type AgentCoreStage } from "./enforcement.js";
|
|
62
|
+
/** `Definition.Cedar` — the plain-Cedar arm of the definition union. */
|
|
63
|
+
export interface AgentCoreCedarDefinition {
|
|
64
|
+
Statement: string;
|
|
65
|
+
}
|
|
66
|
+
/** `Definition.Policy` — the language-agnostic arm, which carries `.dw` text. */
|
|
67
|
+
export interface AgentCoreLanguageDefinition {
|
|
68
|
+
Statement: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The `Definition` property of `AWS::BedrockAgentCore::Policy`.
|
|
72
|
+
*
|
|
73
|
+
* A union rather than a record with two optional keys, because upstream's
|
|
74
|
+
* schema is a `oneOf`: a definition carrying both arms is rejected, and a type
|
|
75
|
+
* that can express it is a type that lets a caller build one.
|
|
76
|
+
*/
|
|
77
|
+
export type AgentCorePolicyDefinition = {
|
|
78
|
+
Cedar: AgentCoreCedarDefinition;
|
|
79
|
+
Policy?: never;
|
|
80
|
+
} | {
|
|
81
|
+
Policy: AgentCoreLanguageDefinition;
|
|
82
|
+
Cedar?: never;
|
|
83
|
+
};
|
|
84
|
+
/** The props of `AWS::BedrockAgentCore::Policy` this module can fill. */
|
|
85
|
+
export interface AgentCorePolicyResource {
|
|
86
|
+
PolicyEngineId: string;
|
|
87
|
+
Name: string;
|
|
88
|
+
Definition: AgentCorePolicyDefinition;
|
|
89
|
+
EnforcementMode?: AgentCoreEnforcementMode;
|
|
90
|
+
Description?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A policy paired with its rollout stage — everything but the engine id.
|
|
94
|
+
*
|
|
95
|
+
* Spreadable into the generated class, which is the point: the caller supplies
|
|
96
|
+
* `PolicyEngineId` (an AttrRef this module has no type for) and this supplies
|
|
97
|
+
* the three props that come from the declaration.
|
|
98
|
+
*/
|
|
99
|
+
export interface AgentCoreStagedPolicy {
|
|
100
|
+
Name: string;
|
|
101
|
+
Definition: AgentCorePolicyDefinition;
|
|
102
|
+
EnforcementMode: AgentCoreEnforcementMode;
|
|
103
|
+
Description?: string;
|
|
104
|
+
}
|
|
105
|
+
/** `Statement` minLength, on both arms of the union. */
|
|
106
|
+
export declare const AGENTCORE_STATEMENT_MIN = 35;
|
|
107
|
+
/** `Statement` maxLength, on both arms of the union. */
|
|
108
|
+
export declare const AGENTCORE_STATEMENT_MAX = 10000;
|
|
109
|
+
/** `Name` — an identifier, and create-only, so a rename replaces the policy. */
|
|
110
|
+
export declare const AGENTCORE_NAME_PATTERN: RegExp;
|
|
111
|
+
/** What a caller can hand the embedding: one policy, or a whole build's worth. */
|
|
112
|
+
export type AgentCorePolicySource = Declarable | CedarPolicyProps | TemporalPolicyProps | Record<string, unknown> | Map<string, Declarable>;
|
|
113
|
+
export interface AgentCoreEmbedOptions {
|
|
114
|
+
/** Override the policy id. Defaults to the serializer's own derivation. */
|
|
115
|
+
policyId?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Force an arm of the `Definition` union.
|
|
118
|
+
*
|
|
119
|
+
* The default reads the policy: temporal clauses take the `Policy` arm, plain
|
|
120
|
+
* Cedar takes the `Cedar` arm. Forcing `"dogwood"` on plain Cedar is
|
|
121
|
+
* legitimate — dogwood embeds Cedar, so the `Policy` arm accepts it, and a
|
|
122
|
+
* policy set that will grow temporal clauses need not change arms later.
|
|
123
|
+
* Forcing `"cedar"` on temporal text is not, and throws.
|
|
124
|
+
*/
|
|
125
|
+
language?: "cedar" | "dogwood";
|
|
126
|
+
/** `Description` on the resource. Free prose; AgentCore does nothing with it. */
|
|
127
|
+
description?: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The policy text for one AgentCore policy — the exact string a `Statement`
|
|
131
|
+
* wants, on whichever arm it lands.
|
|
132
|
+
*
|
|
133
|
+
* `name` is the chant entity name; the `@id` annotation the statement carries
|
|
134
|
+
* is derived from it the same way the serializer derives it, so the statement
|
|
135
|
+
* in the policy engine can be matched back to the declaration that produced it.
|
|
136
|
+
*/
|
|
137
|
+
export declare function agentCoreStatement(name: string, source: AgentCorePolicySource, options?: AgentCoreEmbedOptions): string;
|
|
138
|
+
/**
|
|
139
|
+
* The `Definition` property of `AWS::BedrockAgentCore::Policy`.
|
|
140
|
+
*
|
|
141
|
+
* The arm is chosen by what the policy is: a `Dogwood::TemporalPolicy`, or any
|
|
142
|
+
* props carrying a temporal clause, lands in `Definition.Policy`; plain Cedar
|
|
143
|
+
* lands in `Definition.Cedar`. `options.language` overrides in the one
|
|
144
|
+
* direction that is safe (see {@link AgentCoreEmbedOptions.language}).
|
|
145
|
+
*/
|
|
146
|
+
export declare function agentCorePolicyDefinition(name: string, source: AgentCorePolicySource, options?: AgentCoreEmbedOptions): AgentCorePolicyDefinition;
|
|
147
|
+
/**
|
|
148
|
+
* A policy and its rollout stage, ready to spread into the generated class.
|
|
149
|
+
*
|
|
150
|
+
* The staged-rollout pattern in one call, which is the point (#1660, and the
|
|
151
|
+
* loomster#171 showcase seam): shipping log-only and promoting to enforcing is
|
|
152
|
+
* a one-token diff, not a hand-edited `EnforcementMode` string somewhere else
|
|
153
|
+
* in the template. See ./enforcement.ts for why observe-before-enforce is the
|
|
154
|
+
* default reading of a temporal policy rather than an optional nicety.
|
|
155
|
+
*/
|
|
156
|
+
export declare function agentCoreStagedPolicy(name: string, source: AgentCorePolicySource, stage: AgentCoreStage, options?: AgentCoreEmbedOptions): AgentCoreStagedPolicy;
|
|
157
|
+
/**
|
|
158
|
+
* Every required prop of `AWS::BedrockAgentCore::Policy`, plus the stage.
|
|
159
|
+
*
|
|
160
|
+
* `PolicyEngineId` is a string here rather than an AttrRef because this module
|
|
161
|
+
* does not know the aws lexicon's reference types. A project passes
|
|
162
|
+
* `engine.ref()` in place of the literal and TypeScript is satisfied by the
|
|
163
|
+
* generated class's own prop type, not by this one.
|
|
164
|
+
*/
|
|
165
|
+
export declare function agentCorePolicyResource(name: string, source: AgentCorePolicySource, policyEngineId: string, options?: AgentCoreEmbedOptions & {
|
|
166
|
+
stage?: AgentCoreStage;
|
|
167
|
+
}): AgentCorePolicyResource;
|
|
168
|
+
/**
|
|
169
|
+
* Every policy in a build, as one AgentCore `Definition` each, keyed by chant
|
|
170
|
+
* entity name.
|
|
171
|
+
*
|
|
172
|
+
* The whole-set form, and the one that walks references between declared
|
|
173
|
+
* entities — that is what `cedarPolicyRecords`/`dogwoodPolicyRecords` do. One
|
|
174
|
+
* definition per policy rather than one merged statement, because
|
|
175
|
+
* `EnforcementMode` is a per-policy dial and merging would throw it away; hand
|
|
176
|
+
* the map to {@link agentCorePolicyDefinition} instead when a single AgentCore
|
|
177
|
+
* policy really should carry the whole set.
|
|
178
|
+
*/
|
|
179
|
+
export declare function agentCorePolicySet(entities: Map<string, Declarable>, options?: AgentCoreEmbedOptions): Record<string, AgentCorePolicyDefinition>;
|
|
180
|
+
/**
|
|
181
|
+
* The chant entity name as an AgentCore `Name`.
|
|
182
|
+
*
|
|
183
|
+
* `Name` is create-only and matches `^[A-Za-z][A-Za-z0-9_]*$` — no hyphens,
|
|
184
|
+
* which is why it is not the kebab-case policy id the `@id` annotation carries.
|
|
185
|
+
* Checked rather than coerced: silently rewriting a name that is create-only
|
|
186
|
+
* would mean a later rename replaces the policy without anyone having asked.
|
|
187
|
+
*/
|
|
188
|
+
export declare function agentCorePolicyName(name: string): string;
|
|
189
|
+
//# sourceMappingURL=embed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../../src/agentcore/embed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAmB,KAAK,wBAAwB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpG,wEAAwE;AACxE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iFAAiF;AACjF,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GACjC;IAAE,KAAK,EAAE,wBAAwB,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,2BAA2B,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE3D,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,yBAAyB,CAAC;IACtC,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,yBAAyB,CAAC;IACtC,eAAe,EAAE,wBAAwB,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,wDAAwD;AACxD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,wDAAwD;AACxD,eAAO,MAAM,uBAAuB,QAAQ,CAAC;AAE7C,gFAAgF;AAChF,eAAO,MAAM,sBAAsB,QAA4B,CAAC;AAiBhE,kFAAkF;AAClF,MAAM,MAAM,qBAAqB,GAC7B,UAAU,GACV,gBAAgB,GAChB,mBAAmB,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE5B,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAgGD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAIR;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,qBAA0B,GAClC,yBAAyB,CAY3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,qBAA0B,GAClC,qBAAqB,CAOvB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,EAC7B,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,qBAAqB,GAAG;IAAE,KAAK,CAAC,EAAE,cAAc,CAAA;CAAO,GAC/D,uBAAuB,CASzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAW3C;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUxD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `EnforcementMode` — the dial that makes a policy rollout observable before it
|
|
3
|
+
* is binding (#1660).
|
|
4
|
+
*
|
|
5
|
+
* `AWS::BedrockAgentCore::Policy` carries an optional `EnforcementMode` with
|
|
6
|
+
* exactly two values, and the CloudFormation schema says what they mean:
|
|
7
|
+
*
|
|
8
|
+
* > Whether the policy contributes to the enforce decision returned to Gateway.
|
|
9
|
+
* > LOG_ONLY policies are still evaluated but their decisions are observed
|
|
10
|
+
* > only, allowing customers to validate a policy against real traffic before
|
|
11
|
+
* > promoting it.
|
|
12
|
+
*
|
|
13
|
+
* That is observe-before-enforce, in the substrate, per policy — the same shape
|
|
14
|
+
* chant already has at the ops layer, and the reason epic #1646 picked
|
|
15
|
+
* AgentCore as the deployment target for the temporal dialect rather than
|
|
16
|
+
* inventing a staging mechanism. A temporal policy is the case that needs it
|
|
17
|
+
* most: `formerly within 24h …` cannot be reasoned about from the source alone,
|
|
18
|
+
* because whether it fires depends on traffic nobody has replayed yet.
|
|
19
|
+
*
|
|
20
|
+
* ### The two names, and why chant does not reuse AWS's
|
|
21
|
+
*
|
|
22
|
+
* The wire values are `LOG_ONLY` and `ACTIVE`. `ACTIVE` is a poor name for
|
|
23
|
+
* "enforcing" — it reads as "not disabled", and `LOG_ONLY` is active too; it is
|
|
24
|
+
* evaluated on every request. So the authoring vocabulary here is
|
|
25
|
+
* `"log-only"` / `"enforce"`, and {@link enforcementMode} is the one place the
|
|
26
|
+
* translation happens. The wire values are exported as well, for a caller that
|
|
27
|
+
* has one in hand from a live read.
|
|
28
|
+
*
|
|
29
|
+
* ### The showcase seam (loomster#171)
|
|
30
|
+
*
|
|
31
|
+
* loomster#171 wants a staged policy rollout it can demonstrate end to end:
|
|
32
|
+
* ship the policy log-only, watch what it would have denied, promote it. This
|
|
33
|
+
* module is that seam. The whole rollout is one argument —
|
|
34
|
+
* `agentCoreStagedPolicy(name, policy, stage)` — so the promotion is a
|
|
35
|
+
* one-token diff a reviewer can see, rather than a hand-edited string in a
|
|
36
|
+
* CloudFormation resource. Anything more elaborate (which environments are
|
|
37
|
+
* promoted, who decides) belongs to the caller's own config; this module's job
|
|
38
|
+
* is to make the two states nameable and the transition legible.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* The wire values `EnforcementMode` takes, keyed by the stage they implement.
|
|
42
|
+
*
|
|
43
|
+
* A typed constant pair rather than a bare union so a caller reads
|
|
44
|
+
* `AGENTCORE_ENFORCEMENT.logOnly` at the call site and cannot typo the string.
|
|
45
|
+
*/
|
|
46
|
+
export declare const AGENTCORE_ENFORCEMENT: {
|
|
47
|
+
/** Evaluated on every request; its decision is observed, never returned. */
|
|
48
|
+
readonly logOnly: "LOG_ONLY";
|
|
49
|
+
/** Contributes to the decision Gateway returns. AWS's own default. */
|
|
50
|
+
readonly enforce: "ACTIVE";
|
|
51
|
+
};
|
|
52
|
+
/** The `EnforcementMode` property value, as CloudFormation spells it. */
|
|
53
|
+
export type AgentCoreEnforcementMode = (typeof AGENTCORE_ENFORCEMENT)[keyof typeof AGENTCORE_ENFORCEMENT];
|
|
54
|
+
/** The stage of a rollout, in the vocabulary the seam is authored in. */
|
|
55
|
+
export type AgentCoreStage = "log-only" | "enforce";
|
|
56
|
+
/**
|
|
57
|
+
* The `EnforcementMode` a stage deploys as.
|
|
58
|
+
*
|
|
59
|
+
* Omitting `EnforcementMode` entirely is legal and means `ACTIVE` — AWS's
|
|
60
|
+
* schema declares that default. This helper never returns `undefined`, so a
|
|
61
|
+
* policy that went through it says which stage it is in on the face of the
|
|
62
|
+
* template, and a diff that promotes one shows the change.
|
|
63
|
+
*/
|
|
64
|
+
export declare function enforcementMode(stage: AgentCoreStage): AgentCoreEnforcementMode;
|
|
65
|
+
/** The stage a wire value came from — the inverse of {@link enforcementMode}. */
|
|
66
|
+
export declare function enforcementStage(mode: AgentCoreEnforcementMode | undefined): AgentCoreStage;
|
|
67
|
+
/** True when the policy's decision reaches Gateway rather than only the log. */
|
|
68
|
+
export declare function isEnforcing(mode: AgentCoreEnforcementMode | undefined): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* One line of prose for a stage, for a description or a plan summary.
|
|
71
|
+
*
|
|
72
|
+
* Kept here rather than at the call sites so every surface that explains a
|
|
73
|
+
* staged policy explains it the same way.
|
|
74
|
+
*/
|
|
75
|
+
export declare function describeStage(stage: AgentCoreStage): string;
|
|
76
|
+
//# sourceMappingURL=enforcement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcement.d.ts","sourceRoot":"","sources":["../../src/agentcore/enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;IAChC,4EAA4E;;IAE5E,sEAAsE;;CAE9D,CAAC;AAEX,yEAAyE;AACzE,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC;AAE1G,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,wBAAwB,CAE/E;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,wBAAwB,GAAG,SAAS,GAAG,cAAc,CAE3F;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,EAAE,wBAAwB,GAAG,SAAS,GAAG,OAAO,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAI3D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding embedded AgentCore policy statements in a build's emitted output
|
|
3
|
+
* (#1660).
|
|
4
|
+
*
|
|
5
|
+
* The DWD walls read emitted *text* rather than the in-memory model, for the
|
|
6
|
+
* reason `../dogwood/scan.ts` sets out: `chant audit` runs over artifacts chant
|
|
7
|
+
* did not write, and a wall that only fires on chant's own output is not a
|
|
8
|
+
* wall. An embedded statement is the same situation one lexicon further out —
|
|
9
|
+
* the statement lands in whatever the aws lexicon emitted, so this reads the
|
|
10
|
+
* emitted template rather than reaching for a resource class the cedar lexicon
|
|
11
|
+
* deliberately does not import.
|
|
12
|
+
*
|
|
13
|
+
* Structural, not CloudFormation-specific. The thing being looked for is an
|
|
14
|
+
* object with a `Definition.Policy.Statement` string, which is AgentCore's
|
|
15
|
+
* language-agnostic arm wherever it appears — in a CFN template's
|
|
16
|
+
* `Resources.<id>.Properties`, in a plan JSON, in a fixture. The nearest
|
|
17
|
+
* enclosing key is carried along as the name to blame, which for a CFN template
|
|
18
|
+
* is the logical id.
|
|
19
|
+
*/
|
|
20
|
+
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
21
|
+
/** One `Definition.Policy.Statement` found in an emitted artifact. */
|
|
22
|
+
export interface EmbeddedAgentCoreStatement {
|
|
23
|
+
/** The lexicon whose output carried it. */
|
|
24
|
+
lexicon: string;
|
|
25
|
+
/** The filename, or the lexicon's primary output when it had no name. */
|
|
26
|
+
source: string;
|
|
27
|
+
/** The nearest enclosing key — a CloudFormation logical id, in practice. */
|
|
28
|
+
logicalId?: string;
|
|
29
|
+
/** The statement text, verbatim. */
|
|
30
|
+
statement: string;
|
|
31
|
+
}
|
|
32
|
+
/** The `Cedar` arm as well, for a check that needs to tell the two apart. */
|
|
33
|
+
export interface EmbeddedAgentCoreDefinition extends EmbeddedAgentCoreStatement {
|
|
34
|
+
arm: "Cedar" | "Policy";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Every AgentCore policy definition embedded in a build's emitted output.
|
|
38
|
+
*
|
|
39
|
+
* Non-JSON output is skipped rather than reported: most emitted files are not
|
|
40
|
+
* JSON, and a parse failure here says nothing about whether a statement is
|
|
41
|
+
* there.
|
|
42
|
+
*/
|
|
43
|
+
export declare function embeddedAgentCoreDefinitions(ctx: PostSynthContext): EmbeddedAgentCoreDefinition[];
|
|
44
|
+
/** Only the language-agnostic arm — the one a `.dw` statement travels in. */
|
|
45
|
+
export declare function embeddedAgentCorePolicyStatements(ctx: PostSynthContext): EmbeddedAgentCoreStatement[];
|
|
46
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/agentcore/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,sEAAsE;AACtE,MAAM,WAAW,0BAA0B;IACzC,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,2BAA4B,SAAQ,0BAA0B;IAC7E,GAAG,EAAE,OAAO,GAAG,QAAQ,CAAC;CACzB;AAgDD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,gBAAgB,GAAG,2BAA2B,EAAE,CAoBjG;AAED,6EAA6E;AAC7E,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,gBAAgB,GAAG,0BAA0B,EAAE,CAErG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dogwood dialect's docs pages (#1662, epic #1646).
|
|
3
|
+
*
|
|
4
|
+
* Separate from `./docs.ts` because the dialect is a surface inside this
|
|
5
|
+
* lexicon rather than a lexicon of its own: its pages sit in one sidebar group
|
|
6
|
+
* and get written and reviewed together, while `docs.ts` stays the cedar
|
|
7
|
+
* site's own shape. They are wired in as `extraPages` with `sidebar: false`
|
|
8
|
+
* plus a `sidebarExtra` group, so every page is reachable — Starlight does not
|
|
9
|
+
* auto-discover, and a page no sidebar entry points at exists only for whoever
|
|
10
|
+
* types the URL (#1312).
|
|
11
|
+
*
|
|
12
|
+
* The facts here come from the #1657 upstream verification and from this
|
|
13
|
+
* lexicon's own `src/dogwood/`. Where the two ever disagree the code wins: the
|
|
14
|
+
* builders are what a reader will actually run.
|
|
15
|
+
*/
|
|
16
|
+
export declare const dogwoodOverview = "[Dogwood](https://github.com/dogwood-policy/dogwood) is Cedar with temporal\noperators. A policy can ask what already happened in a session \u2014 was there a\nlogin in the last hour, how much has been transferred in the last fifteen\nminutes, has anything touched a classified document since the session started \u2014\nso approval-before-action, rate limits and budgets become policy instead of\napplication code.\n\nA `.dw` file is a Cedar policy with extra clause forms. Its head is Cedar's,\nbyte for byte, and its action schema is an ordinary `.cedarschema`.\n\n```\n@id(\"read_after_login\")\npermit (\n principal,\n action == Drupe::Action::\"Read\",\n resource\n)\nwhen temporal {\n formerly within 1h Drupe::Action::\"Login\"::response{ input.user: context.input.user }\n};\n```\n\n## Pre-release, and what that means here\n\nUpstream calls itself a reference interpreter and says, in bold on its own\nREADME, that it is **not intended for production use**. The gaps it enumerates:\nno event timestamp validation, no event authentication, no trace durability,\nunsandboxed Rhai in providers, no audit logging, no multi-tenancy isolation,\nand an `http_get` provider with no SSRF protection.\n\nMost of those are a runtime consumer's problem rather than chant's \u2014 chant's\nhalf is authoring, serialization and the walls, and evaluation stays with\nBedrock AgentCore Policy or whatever engine reads the emitted files. The part\nthat *is* chant's problem is that the language surface can move underneath the\ntyped builders, which is the next section.\n\n## How upstream is governed\n\nThere is no versioning story, and that is a finding rather than a complaint.\n\n| Question | Answer at the pinned revision |\n|---|---|\n| Tags | None |\n| GitHub releases | None |\n| Changelog | None |\n| Crate version | `1.0.0`, declared `publish = [\"brazil\"]` \u2014 an Amazon-internal registry, not crates.io |\n| Contributions | CONTRIBUTING declares the repo a read-only mirror, not accepting external PRs, not using GitHub issues |\n| Stability statement | Nowhere in README, CONTRIBUTING, SECURITY or the guide |\n\nEvery content change arrives as one squashed `Sync from internal source`\ncommit from a publish bot, authored against a repository nobody outside Amazon\ncan see. Over the repo's public life the cadence has been roughly one sync\nevery three days. A sync is a wholesale tree replacement, so it can retune the\ngrammar, rename a JSON field or swap the default macro library in a single\ncommit, and the crate will report `1.0.0` either way.\n\nSo a chant version gate cannot key off anything upstream publishes. What\n`src/dogwood/upstream.ts` records instead is a git SHA plus the blob hashes of\nseven files \u2014 three `.pest` grammars, the default macro library, and the three\n`dogwood-cli/src` files whose report structs are the JSON contract. The whole\ntree hash moves on docs-only syncs, which makes it too noisy to gate on.\n\nThree consequences run through everything else on these pages:\n\n- The typed builders target the **parser primitives**, never the named\n aggregates, because the aggregates live in a file a sync can edit and a\n caller can replace. See [Temporal Policies](../dogwood-temporal-policies/).\n- The CLI's **JSON report structs** are the integration surface, never its\n human text, because the human renderer is the likelier thing to get\n cosmetically retuned. See [Validation](../dogwood-validation/).\n- **Nothing in gating CI runs the binary.** Full `.dw` validation is a\n CLI-gated check that says out loud when it did not run.\n\n## A dialect, not a sibling lexicon\n\nk3s beside k3d and forgejo beside github are parallel peers with separate\nupstreams. Dogwood is not a peer: it embeds Cedar, a `.dw` file stripped of\nCedar semantics is meaningless, and the expensive machinery \u2014 schema codegen,\ntyped entity and action classes, meta-policy lint \u2014 is shared verbatim. It\nships as a surface inside this lexicon, with its checks under the `DWD` id\nfamily declared on the serializer's `extraRulePrefixes`.\n\n## Quick start\n\n```typescript\nimport { TemporalPolicy, TemporalEventSchema, dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nexport const events = new TemporalEventSchema({ schema: dogwood.defaultEventSchema() });\n\nexport const readAfterLogin = new TemporalPolicy({\n annotations: { id: \"read_after_login\" },\n action: { eq: 'Drupe::Action::\"Read\"' },\n whenTemporal: [\n dogwood.formerly(\n \"1h\",\n dogwood.predicate('Drupe::Action::\"Login\"', \"response\", {\n \"input.user\": dogwood.ctx(\"input.user\"),\n }),\n ),\n ],\n});\n```\n\n## What comes out\n\n| File | What reads it |\n|---|---|\n| `policies.dw` | `dogwood validate` / `lower` / `replay` |\n| `events.dwschema` | `dogwood --event-schema` \u2014 the service half of the schema |\n| `macros.dw` | `dogwood --macros` \u2014 a macro library, when one is declared non-inline |\n| `<name>.cedar`, `policies.cedar.json` | The plain-Cedar half of the same policy set, unchanged |\n\nA build with no temporal policies emits none of the first three and behaves\nexactly as it did before. A build with both halves emits both from one pass,\nwith policy ids derived the same way on each leg.\n\n## Deploying it: AgentCore\n\n`AWS::BedrockAgentCore::Policy` \u2014 generated by the\n[aws lexicon](/chant/lexicons/aws/) \u2014 is where a temporal policy is actually\ndeployed. Its `Definition` is a two-arm `oneOf`: `Cedar.Statement` for plain\nCedar, `Policy.Statement` for anything else. The second arm is what a `.dw`\npolicy travels in, and it is why the epic picked AgentCore as the target.\n\n```typescript\nimport { agentCoreStagedPolicy } from \"@intentius/chant-lexicon-cedar\";\n\nnew BedrockAgentCorePolicy({\n PolicyEngineId: engine.ref(),\n ...agentCoreStagedPolicy(\"writeNeedsApproval\", writeNeedsApproval, \"log-only\"),\n});\n```\n\n`agentCorePolicyDefinition(name, policy)` picks the arm from the policy itself:\na `TemporalPolicy`, or any props carrying a temporal clause, goes to `Policy`;\nplain Cedar goes to `Cedar`. Nothing in the cedar lexicon imports the aws one \u2014\nthe seam is the data shape, the same rule the AVP embedding follows.\n\n`EnforcementMode` is the staging dial, and a temporal rule is the case that\nneeds it most: `LOG_ONLY` is evaluated on every request with its decision\nobserved rather than returned, so a policy whose behaviour depends on unreplayed\ntraffic can be watched before it binds. Promotion is one token, `\"log-only\"` to\n`\"enforce\"`.\n\nThe resource carries a statement and nothing else, so the event schema has\nnowhere to live in it and is registered with the engine separately. DWDC013\nwarns when a build embeds temporal text and emits no `.dwschema` beside it,\nbecause a deployed statement whose event kinds nobody registered matches\nnothing and stops doing its job without failing.\n\nThe worked example is `lexicons/cedar/examples/agentcore-policy`.\n\n## What chant does not do\n\nchant does not lower. `dogwood lower` compiles a `.dw` set to plain Cedar with\nthe temporal conditions hoisted into `context.*` slots; that is upstream's\nsemantics to own, and a reimplementation would drift the first time a sync\nchanged it. Where the lowered form is wanted, chant shells to the binary.\n\nchant does not evaluate at request time. Temporal decisions are made by the\npolicy engine in front of the traffic, and chant has no seat there. What chant\ndoes have is the offline half: `PolicyReplayOp` replays a declared set against\nrecorded history through upstream's own interpreter and reports where the\nverdicts diverged from what the policy set was supposed to decide.\n\n## The pages\n\n- [Temporal Policies](../dogwood-temporal-policies/) \u2014 the builders, the\n operators, and which of them are macros\n- [Event Schemas](../dogwood-event-schemas/) \u2014 the `.dwschema` surface and the\n `callerPrincipal` pin\n- [Validation](../dogwood-validation/) \u2014 which checks always run and which need\n the binary\n- [Replay](../dogwood-replay/) \u2014 typed traces, `PolicyReplayOp`, and the trap\n that makes half a trace pass silently\n";
|
|
17
|
+
export declare const dogwoodTemporalPolicies = "A `Dogwood::TemporalPolicy` is a `Cedar::Policy` with three extra clause\nforms. Upstream's policy grammar differs from Cedar's in exactly one rule:\n\n```\ncond = { cond_kw ~ (extension_marker | guardrails_tag? ~ \"{\" ~ expr ~ \"}\") }\n```\n\n| Prop | Emits | What it is |\n|---|---|---|\n| `when` / `unless` | `when { \u2026 }` | Ordinary Cedar expression strings, same as `Cedar::Policy` |\n| `whenGuardrails` / `unlessGuardrails` | `when guardrails { \u2026 }` | A Cedar expression with a tag upstream discards when lowering. It marks a clause for a reader; it does not change what the policy means |\n| `whenTemporal` / `unlessTemporal` | `when temporal { \u2026 }` | The temporal sub-language, dispatched to a different parser |\n\nClause order in the emitted file is fixed \u2014 every `when` form, then every\n`unless` form \u2014 rather than taken from the author. Conditions are a\nconjunction, so order carries no meaning, and fixing it means a policy that\ngains a temporal clause does not reshuffle the clauses already there.\n\n## The primitives\n\nThese seven are the whole temporal keyword set in upstream's\n`extension/temporal/grammar.pest`. Everything else you will read about dogwood\nis built out of them.\n\n| Builder | Renders | Notes |\n|---|---|---|\n| `formerly(w, \u03C6)` | `formerly within 1h \u03C6` | \u03C6 held at some point in the window |\n| `previous(w, \u03C6)` | `previous within 30s \u03C6` | \u03C6 held at the immediately preceding timepoint in the window |\n| `since(\u03C6, w, \u03C8)` | `\u03C6 since within 1h \u03C8` | Infix; \u03C6 has held continuously since \u03C8 |\n| `exists(binder, \u03C6)` | `exists (total: Long). \u03C6` | Binds a value for the body to compare |\n| `tp(binder)` | `tp(t)` | Binds the timepoint under evaluation |\n| `count(binders, \u03C6)` | `count for (t: Timepoint). where \u03C6` | The aggregation domain is mandatory |\n| `sum(over, binders, \u03C6)` | `sum a for (a: Long), (t: Timepoint). where \u03C6` | `over` names the summed variable |\n\nPlus `and`, `not`, `compare`, and `predicate` for an event head.\n\nTwo properties of the operator set are worth stating plainly. All of them are\n**past-only** \u2014 there is no future operator, and no way to write one. And\n`formerly`, `previous` and `since` all carry a **mandatory window**: an\ninteger and one of `s`, `m`, `h`, `d`, and nothing else. The builders take the\nwindow as an argument, so a windowless operator has nowhere to live; DWDC012\ncatches the ones that arrive by other routes.\n\n## Four policies\n\nApproval before action:\n\n```typescript\nimport { TemporalPolicy, dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nexport const readAfterLogin = new TemporalPolicy({\n annotations: { id: \"read_after_login\" },\n action: { eq: 'Drupe::Action::\"Read\"' },\n whenTemporal: [\n dogwood.formerly(\n \"1h\",\n dogwood.predicate('Drupe::Action::\"Login\"', \"response\", {\n \"input.user\": dogwood.ctx(\"input.user\"),\n }),\n ),\n ],\n});\n```\n\nA rate limit, from the `count` primitive:\n\n```typescript\nexport const rateLimited = new TemporalPolicy({\n annotations: { id: \"rate_limited\" },\n action: { eq: 'Drupe::Action::\"Transfer\"' },\n whenTemporal: [\n dogwood.compare(\n dogwood.count(\n [dogwood.typedBinder(\"t\", \"Timepoint\")],\n dogwood.formerly(\n \"15m\",\n dogwood.and(dogwood.predicate('Drupe::Action::\"Transfer\"', \"request\"), dogwood.tp(\"t\")),\n ),\n ),\n \"<\",\n 5,\n ),\n ],\n});\n```\n\nA budget, from `sum` behind a macro, with `exists` naming the total:\n\n```typescript\nimport { TemporalMacroLibrary, TemporalPolicy, dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nconst sumFormerly = dogwood.defTemporalMacro(\n \"sum_formerly\",\n [\"?a\", \"?w\", \"?body\"],\n dogwood.sum(\n \"?a\",\n [dogwood.typedBinder(\"?a\", \"Long\"), dogwood.typedBinder(\"$t\", \"Timepoint\")],\n dogwood.formerly(\n dogwood.macroWindow(\"?w\"),\n dogwood.and(dogwood.macroCondition(\"?body\"), dogwood.tp(\"$t\")),\n ),\n ),\n \"Sums the numeric value `?a` over occurrences of `?body` within window `?w`.\",\n);\n\nexport const library = new TemporalMacroLibrary({ macros: [sumFormerly], inline: true });\n\nexport const transferBudget = new TemporalPolicy({\n annotations: { id: \"transfer_sum_over_100\" },\n action: { eq: 'Drupe::Action::\"Alert\"' },\n whenTemporal: [\n dogwood.exists(\n dogwood.typedBinder(\"total\", \"Long\"),\n dogwood.and(\n dogwood.compare(\n dogwood.call(\"sum_formerly\", [\n dogwood.varRef(\"a\"),\n dogwood.interval(\"1h\"),\n dogwood.predicate('Drupe::Action::\"Transfer\"', \"request\", {\n \"input.user\": dogwood.varRef(\"_\"),\n \"input.amount\": dogwood.varRef(\"a\"),\n }),\n ]),\n \"==\",\n dogwood.varRef(\"total\"),\n ),\n dogwood.compare(dogwood.varRef(\"total\"), \">\", 100),\n ),\n ),\n ],\n});\n```\n\nSequencing, with a guardrail and a break-glass exemption:\n\n```typescript\nexport const noToolAfterSensitiveRead = new TemporalPolicy({\n effect: \"forbid\",\n annotations: { id: \"no_tool_after_sensitive_read\" },\n action: { eq: 'Drupe::Action::\"Invoke\"' },\n whenGuardrails: ['context.input.tool != \"audit\"'],\n whenTemporal: [\n dogwood.since(\n dogwood.predicate('Drupe::Action::\"Read\"', \"response\", {\n \"output.classification\": dogwood.varRef(\"c\"),\n }),\n \"30m\",\n dogwood.predicate('Drupe::Action::\"Login\"', \"request\"),\n ),\n ],\n unless: ['principal in Drupe::Group::\"breakglass\"'],\n});\n```\n\nThose four emit this, and the golden test in `src/dogwood/serialize.test.ts`\npins it byte for byte:\n\n```\n// Sums the numeric value `?a` over occurrences of `?body` within window `?w`.\ndef temporal sum_formerly(?a, ?w, ?body) {\n sum ?a for (?a: Long), ($t: Timepoint). where formerly within ?w (?body && tp($t))\n};\n\n@id(\"read_after_login\")\npermit (\n principal,\n action == Drupe::Action::\"Read\",\n resource\n)\nwhen temporal {\n formerly within 1h Drupe::Action::\"Login\"::response{ input.user: context.input.user }\n};\n\n@id(\"transfer_sum_over_100\")\npermit (\n principal,\n action == Drupe::Action::\"Alert\",\n resource\n)\nwhen temporal {\n exists (total: Long). (sum_formerly(a, 1h, Drupe::Action::\"Transfer\"::request{ input.user: _, input.amount: a })) == total && total > 100\n};\n\n@id(\"no_tool_after_sensitive_read\")\nforbid (\n principal,\n action == Drupe::Action::\"Invoke\",\n resource\n)\nwhen guardrails { context.input.tool != \"audit\" }\nwhen temporal {\n Drupe::Action::\"Read\"::response{ output.classification: c } since within 30m Drupe::Action::\"Login\"::request{}\n}\nunless { principal in Drupe::Group::\"breakglass\" };\n\n@id(\"rate_limited\")\npermit (\n principal,\n action == Drupe::Action::\"Transfer\",\n resource\n)\nwhen temporal {\n (count for (t: Timepoint). where formerly within 15m (Drupe::Action::\"Transfer\"::request{} && tp(t))) < 5\n};\n```\n\n## Primitives versus macros\n\nThis is the distinction to get right, and the reason the builder list above is\nshorter than most write-ups of dogwood.\n\n`count_within`, `sum_within` and `count_distinct_within` are **not**\noperators. They are macros defined in\n`dogwood-language/configuration/default_macros.dw`, alongside `bind`:\n\n```\ndef temporal count_within(?w, ?s) {\n count for ($t: Timepoint). where (formerly within ?w (?s && tp($t)))\n};\n```\n\n`once` is not even that. It appears in upstream's examples as an ordinary\nuser-defined macro and ships in no library at all. (The grammar rule behind\n`formerly` is internally named `once_op`, which is where the confusion\nstarts.) If you want `once`, define it \u2014 chant will not pretend it exists.\n\nA caller who passes `--macros` replaces the entire default library, so a\npolicy built on `count_within` is a policy built on an assumption about the\nfar end. chant therefore exposes the four as **calls**:\n\n```typescript\ndogwood.countWithin(\"15m\", dogwood.predicate('Drupe::Action::\"Transfer\"', \"request\"));\n// count_within(15m, Drupe::Action::\"Transfer\"::request{})\n```\n\nA call that resolves to nothing at the other end is a missing-macro error,\nwhich is comprehensible. A first-class builder emitting a name the callee's\nlibrary does not define would be a mystery.\n\nThe way to stop assuming is to emit the definitions yourself:\n\n```typescript\nimport { TemporalMacroLibrary, dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nexport const macros = new TemporalMacroLibrary({ macros: dogwood.defaultMacroLibrary() });\n```\n\nThat writes `macros.dw` with upstream's four definitions verbatim. With\n`inline: true` they go at the top of `policies.dw` instead, and a policy set's\nown `def` shadows a same-named library macro \u2014 which makes inlining the\nstrongest form: the definitions travel with the policies and win over whatever\n`--macros` the caller supplies.\n\n## Writing macros\n\n```typescript\ndogwood.defTemporalMacro(\"once\", [\"?w\", \"?s\"], dogwood.formerly(dogwood.macroWindow(\"?w\"), dogwood.macroCondition(\"?s\")));\ndogwood.defCedarMacro(\"is_small\", [\"?n\"], \"?n < 100\");\n```\n\nTwo sigils, and they are not interchangeable:\n\n- `?p` splices the call-site argument literally. Build one with\n `macroWindow(\"?w\")` in window position, `macroCondition(\"?s\")` in condition\n position, `macroTerm(\"?a\")` in term position.\n- `$t` is a fresh binder the macro introduces, gensym'd at every expansion.\n\nBoth are legal only inside a macro body; upstream's well-formedness pass\nrejects them anywhere else, so the builders validate them at definition time.\n\nA call site supplies a window as a **bare interval** \u2014 `once(1h, \u2026)`, no\n`within` \u2014 because the keyword belongs to the operator and stays in the body.\nThat is `dogwood.interval(\"1h\")`.\n\n## Terms\n\nNumbers and booleans lift to literals. A bare string does not, and that is\ndeliberate: `\"alice\"` is a Cedar string literal and `alice` is a binder\nreference, and guessing which one was meant is how a policy silently stops\nmatching.\n\n| Builder | Renders |\n|---|---|\n| `str(\"alice\")` | `\"alice\"` |\n| `varRef(\"a\")` | `a` |\n| `ctx(\"input.user\")` | `context.input.user` |\n| `scopeRef(\"principal\", \"dept\")` | `principal.dept` |\n| `entityUid('Drupe::OAuthUser::\"alice\"')` | `Drupe::OAuthUser::\"alice\"` |\n| `decimalOf(\"1.50\")` | `decimal(\"1.50\")` |\n| `arrayOf(1, 2)` | `[1, 2]` |\n| `wildcard()` | `*` |\n\n## Precedence, and who handles it\n\nThe renderer parenthesises rather than relying on the reader knowing the\ngrammar. `!` binds tighter than `since` and `&&`, so `!a since within W b`\nnegates only `a`; an aggregate's `where` body is greedy, so\n`count for (\u2026). where \u03C6 == 3` would read `== 3` as part of \u03C6. Aggregates and\nmacro calls in comparison position are wrapped on both sides, and `exists`\nbinds maximally to the right so it is wrapped inside an `&&` chain.\n\n## The escape hatch\n\n`dogwood.raw(\"formerly within 1h \u2026\")` emits temporal source verbatim. It is\nthe one builder that can produce something the walls exist to catch, which is\nwhy the walls read the serialized text rather than the in-memory tree \u2014 see\n[Validation](../dogwood-validation/).\n\n## Next\n\n- [Event Schemas](../dogwood-event-schemas/) \u2014 what the `request`/`response`\n kinds in those predicates come from\n- [Validation](../dogwood-validation/) \u2014 what checks a policy set before it\n leaves the build\n";
|
|
18
|
+
export declare const dogwoodEventSchemas = "A dogwood policy set is checked against two schemas, and only one of them is\nrequired.\n\n| Half | Format | Flag | Required |\n|---|---|---|---|\n| Action schema | Cedar `.cedarschema` \u2014 entities, actions, each action's `context` | `--policy-schema` | Yes, for `validate`, `lower` and `replay` |\n| Service schema | `.dwschema` event DSL, a `providers.json`, a `.dw` macro library | `--event-schema`, `--providers`, `--macros` | No |\n\nThe action schema is the one the rest of this lexicon already generates from \u2014\nsee [Schema](../schema/). This page is about the other half.\n\nWith all three service flags omitted, upstream falls back to\n`ServiceSchema::defaults()`: `request` (deciding), `response` and `error`\nkinds, a universal `pin callerPrincipal = principal`, a 24h `max_window` cap,\nno providers, and the embedded default macro library.\n\n## The `.dwschema` surface\n\nThe grammar is 136 lines of pest and purely syntactic: an optional\n`max_window` directive, then a sequence of event declarations.\n\n```\nmax_window = 30d\n\ndecision event <A>::request {\n ...inputs(A),\n pin callerPrincipal: principalType(A) = principal,\n callerResource: resourceType(A),\n requestId: String,\n}\n```\n\n`A` is a symbolic action binder, not an action. **The file names no actions at\nall** \u2014 it says what shape an event of each kind has, for whichever action it\nis derived against. That is why DWDC010 can check a predicate's event *kind*\nagainst the emitted schema but not its action: the action half of that check\nlives in the `.cedarschema`, and it is the CLI's to make.\n\nEvent kind names are author-defined. `request`, `response` and `error` are\nconventional, not fixed.\n\n| Builder | Emits |\n|---|---|\n| `spreadInputs()` / `spreadOutputs()` | `...inputs(A)` / `...outputs(A)` |\n| `field(\"requestId\", concrete(\"String\"))` | `requestId: String` |\n| `field(\"callerResource\", resourceType())` | `callerResource: resourceType(A)` |\n| `field(\"meta\", record([\u2026]))` | a nested record, addressed as `meta.member` |\n| `pinnedField(name, type, pinPrincipal())` | `pin name: \u2026 = principal` |\n| `pinnedField(name, type, pinContext(\"input.user\"))` | `pin name: \u2026 = context.input.user` |\n\nA pinned field must be a leaf; upstream requires the `pin` prefix and the\n`= \u2026` clause together, and the builder enforces both rather than deferring to\nthe parser.\n\n## The default, and the pin\n\n```typescript\nimport { TemporalEventSchema, dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nexport const events = new TemporalEventSchema({ schema: dogwood.defaultEventSchema() });\n```\n\nThat reproduces upstream's `pinned.dwschema` \u2014 the shape\n`ServiceSchema::defaults()` uses \u2014 and emits `events.dwschema`:\n\n```\n// The default event-schema shape: request/response/error, each correlated to\n// the deciding request's principal.\n\ndecision event <A>::request {\n ...inputs(A),\n pin callerPrincipal: principalType(A) = principal,\n callerResource: resourceType(A),\n requestId: String,\n sessionId: String,\n}\n\nevent <A>::response {\n ...inputs(A),\n ...outputs(A),\n pin callerPrincipal: principalType(A) = principal,\n callerResource: resourceType(A),\n requestId: String,\n sessionId: String,\n}\n\nevent <A>::error {\n ...inputs(A),\n pin callerPrincipal: principalType(A) = principal,\n callerResource: resourceType(A),\n requestId: String,\n sessionId: String,\n}\n```\n\n**The pin is the thing to understand before writing your own schema.**\n`pin callerPrincipal = principal` correlates every temporal predicate to the\ndeciding request's principal: events logged by other principals are invisible\nto `formerly`, `since` and every aggregate over them.\n\nSupplying *any* event schema opts out of upstream's default wholesale. So a\nschema emitted without a pin does not merely fail to add a correlation \u2014 it\nremoves one the policy author very likely assumed, and every predicate in the\nset starts matching other principals' events.\n\nThat is a legitimate design; cross-principal correlation is a reason to write\nyour own schema. It is also a decision, so chant makes it a named argument:\n\n```typescript\nexport const events = new TemporalEventSchema({\n schema: dogwood.defaultEventSchema({ pinCallerPrincipal: false }),\n});\n```\n\nwhich stamps the reasoning into the emitted file as a comment, and which\nDWDS010 reports as a warning in the build. Neither stops you. Both make the\nchoice visible in a diff.\n\n## `max_window`\n\nThe directive caps how far back any operator in the set may look. Absent, the\ncap is upstream's 24h default \u2014 the same 24h that applies when no schema is\nsupplied at all.\n\n```typescript\ndogwood.defaultEventSchema({ maxWindow: \"30d\" }); // max_window = 30d\n```\n\nDWDC011 does the arithmetic in TypeScript and fails the build on a window past\nthe cap, with no binary involved. Where several schemas are emitted the\ntightest cap wins, and macro-call intervals count: `once(48h, \u2026)` expands\nthrough `within ?w` and looks back exactly as far as `formerly within 48h`.\n\n## Several schemas\n\nOne `.dwschema` per file, because `max_window` is a single directive at the\ntop and concatenating two schemas would emit something upstream rejects. A\nbuild with more than one gives each an explicit filename:\n\n```typescript\nexport const gateway = new TemporalEventSchema({\n schema: dogwood.defaultEventSchema({ maxWindow: \"30d\" }),\n filename: \"gateway.dwschema\",\n});\n```\n\nTwo schemas targeting one filename is a serializer warning and only the first\nis written \u2014 a silent merge would produce a file that parses as neither.\n\n## Providers\n\nThe third service flag, `--providers`, takes a `providers.json` whose entries\ncarry `argumentTypes`, an `outputType` and an `implementation`. chant has no\ntyped builder for it today; the CLI adapter's bundle type accepts provider text\nif you assemble it, and the build's planner does not emit one.\n\nOne upstream trap worth recording even so: the CLI reads `--providers` as raw\ntext and **never resolves `scriptFile`**. Rhai has to be inlined under\n`implementation.script`, or `replay` fails per-evaluation with \"rhai\nimplementation has no script\" while `validate` and `lower` still pass.\n\n## Next\n\n- [Validation](../dogwood-validation/) \u2014 DWDC010, DWDC011 and DWDS010 in full\n- [Replay](../dogwood-replay/) \u2014 where the events these schemas describe\n actually come from\n";
|
|
19
|
+
export declare const dogwoodValidation = "Validation splits by what needs a binary, and the split is the point.\n\nEverything answerable in TypeScript runs on every build and gates. Full `.dw`\nvalidation needs upstream's own frontend, which ships as a Rust CLI and nothing\nelse \u2014 no npm package, no wasm build, no bindings \u2014 so it runs when the binary\nis there and says so out loud when it is not.\n\n| Check | Severity | Needs the binary |\n|---|---|---|\n| DWDC010 \u2014 a temporal predicate names a declared event kind | error | no |\n| DWDC011 \u2014 a window fits inside `max_window` | error | no |\n| DWDC012 \u2014 `formerly`/`previous`/`since` carries its window | error | no |\n| DWDC013 \u2014 an embedded AgentCore temporal statement has its event schema emitted | warning | no |\n| DWDS010 \u2014 an emitted event schema pins something | warning | no |\n| DWDE010 \u2014 the set validates clean under `dogwood validate` | error | yes |\n| DWDE011 \u2014 the lowered Cedar validates under `cedar-wasm` | error | yes |\n\nThe DWD family is an ordinary set of\n[post-synth checks](/chant/guide/organizational-policy/) under the prefix the\ncedar serializer declares in `extraRulePrefixes`. There is no second policy\nengine here; dogwood is a target, the same as Cedar.\n\nEvery one of them reads the **emitted text**, not the in-memory model, for the\nsame reason the CED checks read `policies.cedar.json`: `chant audit` runs over\na checked-in artifact chant did not write, and a wall that only fires on\nchant's own output is not a wall. It also keeps the builders and the walls\nindependent \u2014 DWDC012 catches a windowless `formerly` even though the builders\ncannot construct one, because `raw()` and a hand-written `.dw` both can.\n\n## The TypeScript walls\n\n**DWDC010** compares every predicate head in the temporal regions of a `.dw`\nfile against the event kinds the emitted `.dwschema` declares. Upstream rejects\nthe same thing with code `extension`. The check is silent when no `.dwschema`\nwas emitted: with none supplied, `ServiceSchema::defaults()` decides the kinds\nat the far end, and guessing that a project's out-of-band schema matches\nupstream's default would fail builds for a policy set that is fine.\n\n**DWDC011** fires with or without an emitted schema, because the cap applies\neither way \u2014 24h by default. See\n[Event Schemas](../dogwood-event-schemas/#max_window).\n\n**DWDC012** is the wall behind the typed builders. `formerly(w, body)` has\nnowhere to put a missing window, so the builders make it unrepresentable; the\ncheck is what covers `raw()`, hand-written files, and audits of trees chant\nnever wrote.\n\n**DWDC013** asks the question prior to DWDC010's, and only of statements that\nleft the `.dw` file behind. A policy embedded in `Definition.Policy.Statement`\ntravels as one string; the engine at the other end cannot match a temporal\npredicate until it knows what an event is. A build that embeds temporal text\nand emits no `.dwschema` has shipped half a policy \u2014 the statement deploys, the\npredicates match nothing, and a `formerly`-guarded forbid stops denying.\nWarning rather than error, because a project may register the service schema\nthrough a separate pipeline, and failing that build would be chant asserting a\nfact it cannot check.\n\n**DWDS010** is report-only. chant does not know whether cross-principal\ncorrelation was wanted, only that an unpinned schema should not slip through a\nreview unremarked.\n\nScanning is confined to the temporal regions of a file \u2014 every\n`temporal { \u2026 }` body and every `def temporal` body \u2014 so a Cedar attribute\nnamed `since` is not mistaken for the operator, and `context.retryWindow == 3`\nis not mistaken for a window.\n\n## The CLI-gated half\n\n**DWDE010** runs `dogwood validate --format json` over each emitted policy set\nand reports every finding. What it catches that the walls cannot: macro\nexpansion, the temporal type checker, and the Cedar body checked against the\naction schema through upstream's own frontend.\n\n**DWDE011** takes the `dogwood lower` output \u2014 plain Cedar with the temporal\nconditions hoisted into `context.*` slots, plus an augmented schema declaring\nthem \u2014 and runs the published `@cedar-policy/cedar-wasm` over it. That is a\ndifferent validator from the one vendored inside upstream, which makes a\nfinding here meaningful: it is drift between the Cedar upstream pins and the\nCedar the rest of chant validates against. The #1657 verification put all 86\nupstream example bundles through this exact path and every one validated clean\nin strict mode.\n\n### When the binary is absent\n\nOne `info` finding, naming the binary, where chant looked, and the issue. Not\nsilence. A check that quietly passes when it could not run is claiming a\nguarantee it never made.\n\n## Pointing chant at a binary\n\nThere is no published build. You build it from the pinned revision:\n\n```bash\ngit clone https://github.com/dogwood-policy/dogwood\ncd dogwood && git checkout 5063bcc2d6d6cf5024d1b0498e6cc8ef52cbcf0c\ncargo build --release\n```\n\nResolution order:\n\n1. An explicit `configureDogwoodCli({ binary })` call \u2014 taken as given, since\n its caller knows.\n2. `$CHANT_DOGWOOD_BINARY`.\n3. `cedar.dogwood.binary` in a `chant.config.json`, resolved by walking up\n from the working directory.\n4. `dogwood` on `PATH`.\n\n```bash\nexport CHANT_DOGWOOD_BINARY=/path/to/dogwood/target/release/dogwood\n```\n\n```json\n{ \"cedar\": { \"dogwood\": { \"binary\": \"./vendor/dogwood\" } } }\n```\n\nThe config knob reads `chant.config.json` only, and that is a real limitation\nrather than an oversight: a post-synth check's `check()` is synchronous, while\nchant's config loader is async and, under `chant build --sandbox`, evaluates a\n`chant.config.ts` in a child process. JSON is data, so reading it executes\nnothing. A project on `chant.config.ts` uses the environment variable or the\nprogrammatic override.\n\nA path from the environment or the config that is not executable is resolved\npast rather than returned to fail later, and the advisory names where chant\nlooked.\n\n## Why exit codes decide nothing\n\nThree properties of the CLI shape the adapter, all verified against the pinned\nsources.\n\n**Exit 2 is ambiguous.** It covers a rejected policy set *and* clap's own usage\nerror for an unknown flag \u2014 and upstream's published guide claims exit 1 for\nthe latter. Reading a bare non-zero exit as \"your policy is bad\" would fail a\nbuild over a flag rename in a sync nobody outside Amazon can review. So the\nadapter branches on the JSON on stdout, in both directions: a `passed: false`\nwith a zero exit is still a rejection, and the reverse is still a pass.\n\n**There are two JSON shapes.** A type-check finding arrives in a report \u2014\n`passed`, `passed_without_warnings`, `errors[]`, `warnings[]`. A fatal parse,\nmacro or lowering error replaces the whole report with a bare error object\ncarrying the same diagnostic fields at the top level plus `related[]`. Both\nnormalize into one diagnostic type, so nothing downstream has to know which\narrived.\n\n**A run that produced no usable JSON is neither a pass nor a rejection.** It is\nreported at `warning` severity as \"could not be validated\", and the policy set\nis explicitly described as neither accepted nor rejected.\n\nTwo smaller contract facts the adapter encodes: `--format json` writes to\nstdout for success and fatal alike, and `--emit` is ignored under\n`--format json` (the JSON always carries all three lowered artifacts), so it is\nnot passed.\n\nDiagnostic labels are **byte offsets** into the `.dw` source, and findings\nreport them as byte ranges. Converting to line and column would mean\nre-deriving line breaks over a file the adapter does not hold, and a wrong line\nnumber is worse than an honest offset.\n\n## Nothing in gating CI runs it\n\nBy design, from the epic: upstream instability is priced, not absorbed. The\nCLI-gated checks are for a developer with the binary and for on-demand\nharnesses in the `forgejo-runtime-e2e` shape. `PolicyReplayOp` shares that\nrule and the same binary discovery \u2014 see [Replay](../dogwood-replay/) \u2014 with\none difference: a replay step with no binary **fails**, where a build check\nwith no binary reports and moves on. A check that could not run should not\nblock a build; a replay that could not run has produced no answer at all.\n\n## Next\n\n- [Replay](../dogwood-replay/) \u2014 the third verb, wrapped as an activity and an\n Op rather than as a build check\n- [Lint Rules](../lint-rules/) \u2014 the cedar half of the same check set\n";
|
|
20
|
+
export declare const dogwoodReplay = "`dogwood replay` evaluates a policy set against a recorded event trace and\nreturns a verdict per decision point. It is how a temporal policy gets tested\nat all.\n\nA plain Cedar policy is decidable from its source: given the schema, a build\ncan say whether it parses, whether it type-checks, and what it applies to. The\nDWDC and CEDC checks already do that. A temporal policy is not decidable that\nway \u2014 whether `formerly within 1h Login::response{ \u2026 }` fires depends on a\nhistory nobody has replayed. So the check is a replay against recorded decision\nhistory, and the answer moves as the history does. That puts it on the observe\nend of the lifecycle dial, beside `WorkflowAuditOp`, with a finding mode as the\nreconcile step.\n\nThree pieces ship: a typed trace builder, a `dogwoodReplay` activity, and the\n`PolicyReplayOp` composite that pairs them. The worked example is\n`lexicons/cedar/examples/policy-replay`.\n\n## The Op\n\n```typescript\n// ops/policy-replay.op.ts\nimport { PolicyReplayOp } from \"@intentius/chant-lexicon-cedar\";\nimport { readAfterLoginExpectations } from \"../trace/read-after-login\";\n\nexport const { op } = PolicyReplayOp({\n name: \"policy-replay\",\n policiesPath: \"dist/policies.dw\",\n policySchemaPath: \"schema.cedarschema\",\n eventSchemaPath: \"dist/events.dwschema\",\n tracePath: \"trace/read-after-login.log\",\n expect: readAfterLoginExpectations,\n onFinding: \"report\",\n});\n\nexport default op;\n```\n\n```bash\nnpx chant run policy-replay\n```\n\nThree phases:\n\n| Phase | Step | What it does |\n|---|---|---|\n| Artifacts | `chantBuild` | Emits `policies.dw`, the `.cedarschema` and the `.dwschema` the replay reads. Pass `buildScript: false` when they are checked in and the phase is dropped rather than run empty |\n| Replay | `dogwoodReplay` | Runs `dogwood replay --format json` over the bundle and the trace, writes the divergence report |\n| Report | `dogwoodReplayReport` | Reads that report and acts on the finding mode |\n\nThe report file (`dist/dogwood-replay.json` by default) is the seam between the\nlast two phases, for the same reason `dist/fly.json` is the seam between\n`build:fly` and `flyApply`: Op steps do not hand return values to one another,\nso a phase boundary needs an artifact to be a real boundary.\n\nThe Replay step carries `outcomeAttribute: { name: \"Divergences\", from: \"findings\" }`,\nso \"show me the replays that found something\" is one filter rather than a log\nread. `onFinding` takes `report | issue | pull-request`; `report` prints the\nmarkdown, and the other two hand back a title and body for whatever opens them\n\u2014 the cedar lexicon has no forge client and does not grow one, the same\ndivision `workflowSupplyChainAudit` draws. `failOnDivergence` defaults to\nfalse: an observe-dial Op reports, and a red run is the caller's decision.\n\nThe composite ships from cedar, not from temporal, because it hands back an Op\nand nothing else. It imports `@intentius/chant/op` and carries no dependency on\nthe temporal lexicon. A project that wants it scheduled pairs it with a\n`TemporalSchedule` of its own \u2014 two lines, project-side, rather than a config\nflag that would drag the dependency in for everyone.\n\n## Typed traces\n\n`traceEvent()` builds one line. `renderTrace()` renders a list.\n`traceFixture()` does both and refuses to hand back a trace that would weaken\nits own replay.\n\n```typescript\nimport { dogwood } from \"@intentius/chant-lexicon-cedar\";\n\nconst { entityRef, traceEvent } = dogwood;\n\nconst ALICE = 'Drupe::OAuthUser::\"alice\"';\nconst GATEWAY = 'Drupe::Gateway::\"gw1\"';\n\nconst session = {\n scope: { principal: ALICE, resource: GATEWAY },\n context: { input: { user: \"alice\" } },\n} as const;\n\nconst injected = (requestId: string) => ({\n callerPrincipal: entityRef(ALICE),\n callerResource: entityRef(GATEWAY),\n requestId,\n});\n\nexport const trace = [\n traceEvent({ ...session, timestamp: 0, action: 'Drupe::Action::\"Login\"', record: injected(\"u1\") }),\n traceEvent({ ...session, timestamp: 0, action: 'Drupe::Action::\"Login\"', kind: \"response\", record: injected(\"u1\") }),\n traceEvent({ ...session, timestamp: 10, action: 'Drupe::Action::\"Read\"', record: injected(\"u2\") }),\n traceEvent({ ...session, timestamp: 7200, action: 'Drupe::Action::\"Read\"', record: injected(\"u3\") }),\n];\n```\n\n```\n@0 scope(principal: Drupe::OAuthUser::\"alice\", resource: Drupe::Gateway::\"gw1\") request_context(input: { user: \"alice\" }) Drupe::Action::\"Login\"::request(input: { user: \"alice\" }, callerPrincipal: Drupe::OAuthUser::\"alice\", callerResource: Drupe::Gateway::\"gw1\", requestId: \"u1\")\n```\n\nCompare the input to the output: `input` was written once, under `context`,\nand comes out in the `request_context` envelope **and** in the logged record.\n`kind` defaults to `request`. Values render in Cedar surface\nforms: strings quote themselves, `entityRef()` renders a uid bare,\n`decimalValue(\"1.50\")` keeps a scale a JS number would lose, and a non-integer\n`number` throws rather than emitting something the parser reads differently.\n\n## The both-bags trap\n\nEach line carries two field bags and they are not the same bag.\n\n```\n@10 \u2026 request_context(input: { user: \"alice\" }) Drupe::Action::\"Read\"::request(input: { user: \"alice\" }, callerPrincipal: \u2026)\n \u2514\u2500\u2500 the Cedar request is built from this \u2514\u2500\u2500 temporal predicates match against this\n```\n\n`formerly within 1h Drupe::Action::\"Login\"::response{ input.user: context.input.user }`\ncompares the *past* login's `input.user`, out of the logged record, against the\n*current* request's `context.input.user`, out of the `request_context`\nenvelope. Fill one bag and not the other and nothing errors: the replay exits 0\nwith a verdict that tested half of what it claims.\n\nSo the default is both bags, and the weaker trace takes an explicit opt-out:\n\n| `bags` | Where a `context` group lands |\n|---|---|\n| `\"both\"` (default) | `request_context` and the logged record |\n| `\"record-only\"` | The logged record alone \u2014 `context.*` is absent from the Cedar request |\n| `\"context-only\"` | The envelope alone \u2014 no temporal predicate can match the group |\n\n`record` is the other half of the input, and it is deliberately separate: the\nevent schema's own injections (`callerPrincipal`, `callerResource`,\n`requestId`, `sessionId`) belong to the logged record and are never part of the\nCedar request.\n\n## The action-naming trap\n\nAction names must be fully qualified \u2014 `Drupe::Action::\"Read\"`, never `Read`. A\nshort name leaves every temporal predicate unmatched while Cedar still\nauthorizes. `traceEvent()` rejects one at construction, as do `entityRef()` and\n`traceEntity()`.\n\n## Auditing a trace chant did not build\n\nA trace fetched from somewhere else \u2014 an AgentCore session history, a `.log`\nrecorded by hand \u2014 normalizes into the same `TraceEvent` list and takes the\nsame audit:\n\n```typescript\nconst issues = dogwood.auditTrace(events);\n```\n\n| Kind | What it means |\n|---|---|\n| `single-bag` | A group is in one bag and not the other, so one side of the check silently misses |\n| `no-request-context` | A deciding event has no envelope at all, so every `context.*` test misses |\n| `empty-record` | An event logs no fields, so no temporal predicate can match it |\n| `out-of-order` | A timestamp goes backwards; history accumulates in file order, so a window sees something different |\n\nEvery one of those makes a replay *weaker* rather than making it fail, which is\nthe class a green run hides. `decisionKinds` defaults to `[\"request\"]` \u2014 a\nhistory-only event never becomes a Cedar request, so a missing envelope on one\nis not a weakening and is not reported. The truth is whichever kinds the\nproject's `.dwschema` marks `decision`, and that file is not visible from the\naudit.\n\n`traceFixture(events)` runs the same audit and **throws** on any finding,\nnaming the `allow` list that would let it through. A fixture that weakens its\nown replay fails at build time instead of producing a green run that proves\nnothing.\n\n## Expectations\n\n```typescript\nexport const expectations = [\n { timestamp: 0, verdict: \"deny\", note: \"the login request itself is not permitted\" },\n { timestamp: 10, verdict: \"allow\", determiningRules: [0], note: \"the login is ten seconds old\" },\n { timestamp: 7200, verdict: \"deny\", note: \"the login is two hours stale\" },\n];\n```\n\nThree expectations for four trace lines, and that is the point of writing them\nagainst `timestamp` rather than `index`: `Login::response` is history-only\nunder the default event schema, so it contributes to the window and produces no\nverdict. `index` is the position in the *decision* stream, not the trace line\nnumber, and it shifts whenever a trace gains a history-only event.\n\n`determiningRules` is the second half of the assertion. A decision that comes\nout right for the wrong reason \u2014 the correct verdict carried by a different\nrule \u2014 is drift the verdict alone cannot show.\n\nWhat `compareVerdicts` reports: a verdict that differs from the expectation; a\nverdict that matches but was determined by different rules; a decision point an\nexpectation named that never occurred; a decision point that occurred and\nnothing expected. Per-evaluation errors are reported even when the expectation\nmatched, and \u2014 when no expectations were written at all \u2014 an errored evaluation\nis still a finding, because a provider with no inlined Rhai script would\notherwise replay \"clean\".\n\n## The trace format\n\nOne event per line. Blank lines are skipped, a leading BOM is stripped, and\nthere is **no comment syntax** \u2014 a `//` is an ordinary part of a value, so URLs\nsurvive and an attribution header would be parsed as an event and rejected with\n\"timepoint must start with `@`\".\n\n```\n@<timestamp> [scope(...)] [entities(...)] [request_context(...)] <Ns>::Action::\"<Name>\"::<kind>(<field>: <value>, ...)\n```\n\nThe timestamp is an `i64` after `@`. The three envelopes are optional and must\nappear in that order. Values use Cedar surface forms: entity refs, quoted\nstrings, integers, decimals like `1.50`, booleans, arrays, nested records.\n\n## Reading the run\n\nHuman output is one line per decision point:\n\n```\n@0 (time point 0): DENY\n@10 (time point 1): ALLOW [rules: 0]\n@7200 (time point 2): DENY\n```\n\nJSON gives `{verdicts: [{index, timestamp, verdict, determining_rules, errors}]}`.\nHistory-only events produce no line.\n\n**Replay exits 0 even when every verdict is DENY.** A non-zero exit means the\ntrace or the policy set failed to load, never that a policy denied. The adapter\nin `src/dogwood/cli.ts` reads the JSON and not the exit code, here as\neverywhere; an unrecognised verdict string is read as a deny rather than\ndropped, because dropping an entry would shift every later index.\n\n## It needs the binary, and does not pretend otherwise\n\nThe Replay phase shells to upstream's CLI. There is no npm package and no wasm\nbuild \u2014 see [Validation](../dogwood-validation/) for how chant finds a binary\nand how to build one.\n\nWithout one the step **fails** and says where chant looked. It does not degrade\nto a pass, and an unusable invocation or a fatal (a malformed trace line, an\nunparseable policy set) throws rather than reporting zero divergences. A replay\nthat did not happen is not a replay that found nothing \u2014 which is also why\nnothing in gating CI executes the binary.\n\n## Next\n\n- [Validation](../dogwood-validation/) \u2014 the two verbs that run inside a build,\n and the binary knobs replay shares\n- [The Dogwood Dialect](../dogwood/) \u2014 what pre-release means for all of this\n";
|
|
21
|
+
//# sourceMappingURL=docs-dogwood.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-dogwood.d.ts","sourceRoot":"","sources":["../../src/codegen/docs-dogwood.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,eAAO,MAAM,eAAe,oiQA+K3B,CAAC;AAIF,eAAO,MAAM,uBAAuB,ghXA0TnC,CAAC;AAIF,eAAO,MAAM,mBAAmB,q6MAsK/B,CAAC;AAIF,eAAO,MAAM,iBAAiB,49QA8K7B,CAAC;AAIF,eAAO,MAAM,aAAa,inXA+PzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAqxBH;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+HjF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/codegen/package.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/codegen/package.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,kCAAkC,CAAC;AAG1C,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AAI9C;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CA6BtF"}
|