@substrat-run/contract-tests 0.98.1 → 0.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/grant-expiry-suite.d.ts +14 -0
- package/dist/grant-expiry-suite.d.ts.map +1 -0
- package/dist/grant-expiry-suite.js +181 -0
- package/dist/grant-expiry-suite.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/modules.d.ts +236 -0
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +32 -3
- package/dist/modules.js.map +1 -1
- package/dist/schedule-suite.d.ts.map +1 -1
- package/dist/schedule-suite.js +9 -1
- package/dist/schedule-suite.js.map +1 -1
- package/dist/scope-host-suite.d.ts +7 -0
- package/dist/scope-host-suite.d.ts.map +1 -1
- package/dist/scope-host-suite.js +255 -0
- package/dist/scope-host-suite.js.map +1 -1
- package/dist/timeline-suite.d.ts.map +1 -1
- package/dist/timeline-suite.js +6 -0
- package/dist/timeline-suite.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -42,6 +42,29 @@ scopeHostContractSuite('adapter-yours', async () => {
|
|
|
42
42
|
The suite grows with the kernel (migration journal, crash-mid-migration,
|
|
43
43
|
duplicate-delivery harnesses); adapters inherit new checks by upgrading.
|
|
44
44
|
|
|
45
|
+
## Suites gated by mounting, not by a flag
|
|
46
|
+
|
|
47
|
+
Most suites take a `ScopeHostFixture` and every adapter mounts every one. A few need
|
|
48
|
+
something only some hosts can provide, and those are separate exports an adapter
|
|
49
|
+
mounts only when it can satisfy the fixture. There is deliberately no capability flag
|
|
50
|
+
that makes a shared suite skip on one adapter: a skipped test reads as coverage the
|
|
51
|
+
adapter does not have.
|
|
52
|
+
|
|
53
|
+
- **`grantExpiryContractSuite`** — the fixture returns `{ host, clock, cleanup }` where
|
|
54
|
+
`clock` is the `ManualClock` (from `@substrat-run/kernel`) the host was constructed
|
|
55
|
+
with. The suite grants a permission with an `expiresAt` an hour ahead, asserts it is
|
|
56
|
+
live, moves the clock past it and asserts the denial — the transition the wall clock
|
|
57
|
+
cannot show in a test. Mounted by `adapter-sqlite` (`new SqliteScopeHost({ dir,
|
|
58
|
+
clock: clock.read })`).
|
|
59
|
+
|
|
60
|
+
**Parity gap, stated:** `adapter-cloudflare` does not mount it. The Durable Object
|
|
61
|
+
reads the wall clock inside the DO, which workerd constructs — an option on
|
|
62
|
+
`CloudflareScopeHost` never reaches it, because the host only holds a stub. Getting a
|
|
63
|
+
clock there is a decision (caller-supplied `now` per invocation, a test-only seam, or
|
|
64
|
+
neither), tracked on #956. Until one is taken, the DO's checker runs the same
|
|
65
|
+
`expires_at` predicate against a `now` it reads itself, and the pure host is the one
|
|
66
|
+
held to the contract by this suite.
|
|
67
|
+
|
|
45
68
|
## Status
|
|
46
69
|
|
|
47
70
|
Pre-release (0.x): the suite expands as kernel contracts land.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ManualClock, type ScopeHost } from '@substrat-run/kernel';
|
|
2
|
+
/**
|
|
3
|
+
* What the fixture hands the suite. `clock` is the SAME `ManualClock` whose
|
|
4
|
+
* `read` the host was constructed with — the suite advances it and expects the
|
|
5
|
+
* host to notice. A fixture that built the host on a different clock would pass
|
|
6
|
+
* the "allowed" half and fail every "denied" one, which is the honest failure.
|
|
7
|
+
*/
|
|
8
|
+
export interface GrantExpiryFixture {
|
|
9
|
+
host: ScopeHost;
|
|
10
|
+
clock: ManualClock;
|
|
11
|
+
cleanup: () => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export declare function grantExpiryContractSuite(adapterName: string, makeFixture: () => Promise<GrantExpiryFixture>): void;
|
|
14
|
+
//# sourceMappingURL=grant-expiry-suite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant-expiry-suite.d.ts","sourceRoot":"","sources":["../src/grant-expiry-suite.ts"],"names":[],"mappings":"AAgDA,OAAO,EAAQ,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAM9E;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAKD,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,GAC7C,IAAI,CAoJN"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract suite for grant expiry under an injected clock (#956).
|
|
3
|
+
*
|
|
4
|
+
* What it pins is one sentence: **a grant with an `expiresAt` stops granting the
|
|
5
|
+
* moment the HOST's clock passes it — not the wall clock, the host's.**
|
|
6
|
+
*
|
|
7
|
+
* `permissionContractSuite` already proves an ALREADY-expired grant is refused
|
|
8
|
+
* (dave's, dated 2000). What it cannot prove is the transition: a grant that is
|
|
9
|
+
* live now and dead an hour later, because the only way to get there against the
|
|
10
|
+
* wall clock is to wait. The pure host takes a `clock` (#812), and since #1160 its
|
|
11
|
+
* checker judges `expires_at` against that clock rather than `new Date()` — this
|
|
12
|
+
* suite is what holds it there. Without it, a refactor that quietly reverted the
|
|
13
|
+
* checker to the wall clock would pass every other suite: the dead grant of 2000
|
|
14
|
+
* is dead on both clocks.
|
|
15
|
+
*
|
|
16
|
+
* **Mounted, not flagged.** The fixture returns a `ManualClock` the suite moves,
|
|
17
|
+
* so only an adapter that can hand its host a clock can mount it. That is the
|
|
18
|
+
* pure SQLite host today. It is deliberately NOT a capability flag on the shared
|
|
19
|
+
* fixture that skips on the other adapter: a skipped test reads as coverage the
|
|
20
|
+
* adapter does not have.
|
|
21
|
+
*
|
|
22
|
+
* **Why the Cloudflare adapter does not mount it (the parity gap, written down).**
|
|
23
|
+
* The Durable Object host reads the wall clock inside the DO
|
|
24
|
+
* (`packages/adapter-cloudflare/src/scope-do.ts`, the `at` read in `invoke`, and
|
|
25
|
+
* the entitlement / system-grant reads beside it). The DO is constructed by
|
|
26
|
+
* workerd, not by `CloudflareScopeHost`, so an option on the host factory never
|
|
27
|
+
* reaches it — the host only holds a stub. The three ways a clock could get there
|
|
28
|
+
* were each a decision rather than a patch, and none was taken unattended:
|
|
29
|
+
* (a) the host sends the instant with each invocation, which makes `now`
|
|
30
|
+
* caller-supplied — a different trust story; (b) a test-only seam (an env flag
|
|
31
|
+
* or a DO method a test calls), honest but explicitly not the production path;
|
|
32
|
+
* (c) leave the fact untestable there and say so. This suite is (c): the pure
|
|
33
|
+
* host is held to the contract, the DO's checker runs the same SQL predicate
|
|
34
|
+
* (`expires_at IS NULL OR expires_at > ?`) against a `now` it reads itself, and
|
|
35
|
+
* the day the DO can take a clock, mounting this suite is the whole change.
|
|
36
|
+
*/
|
|
37
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
38
|
+
import { instant, permissionKey, platformActorId, principalId, scopeId, tenantId, } from '@substrat-run/contracts';
|
|
39
|
+
import { ulid } from '@substrat-run/kernel';
|
|
40
|
+
import { permMod } from './modules.js';
|
|
41
|
+
const PERM_READ = permissionKey.parse('perm:read');
|
|
42
|
+
const PERM_USE = permissionKey.parse('perm:use');
|
|
43
|
+
const START = '2026-03-01T09:00:00.000Z';
|
|
44
|
+
const HOUR = 3_600_000;
|
|
45
|
+
export function grantExpiryContractSuite(adapterName, makeFixture) {
|
|
46
|
+
describe(`grant expiry under an injected clock: ${adapterName}`, () => {
|
|
47
|
+
let fixture;
|
|
48
|
+
let host;
|
|
49
|
+
let clock;
|
|
50
|
+
const t1 = tenantId.parse(ulid());
|
|
51
|
+
const s1 = scopeId.parse(ulid());
|
|
52
|
+
const alice = principalId.parse(ulid()); // grantedBy
|
|
53
|
+
const nora = principalId.parse(ulid()); // node-level, timed
|
|
54
|
+
const eve = principalId.parse(ulid()); // entity-narrowed, timed
|
|
55
|
+
const staff = platformActorId.parse(ulid());
|
|
56
|
+
const box = { entityType: 'box', entityId: 'b1' };
|
|
57
|
+
const probe = async (who, permission, entity) => {
|
|
58
|
+
const stub = await host.getScope(who, t1, s1);
|
|
59
|
+
const decision = await stub.invoke('perm/probe', { permission, entity });
|
|
60
|
+
return decision.allowed;
|
|
61
|
+
};
|
|
62
|
+
const at = (ms) => instant.parse(new Date(Date.parse(START) + ms).toISOString());
|
|
63
|
+
beforeAll(async () => {
|
|
64
|
+
fixture = await makeFixture();
|
|
65
|
+
host = fixture.host;
|
|
66
|
+
clock = fixture.clock;
|
|
67
|
+
clock.set(START);
|
|
68
|
+
host.registerModule(permMod);
|
|
69
|
+
await host.admin.createTenant(staff, { id: t1, slug: 'expiry-tenant', name: 'Expiry Tenant' });
|
|
70
|
+
await host.admin.grantEntitlement(staff, t1, 'perm');
|
|
71
|
+
await host.provisionScope(staff, { tenantId: t1, scopeId: s1, vertical: 'expiry-vertical' });
|
|
72
|
+
await host.admin.activateScope(staff, t1, s1);
|
|
73
|
+
// Both shapes a timed grant takes: node-level, and narrowed to one entity.
|
|
74
|
+
await host.admin.grant(staff, {
|
|
75
|
+
principalId: nora,
|
|
76
|
+
permission: PERM_READ,
|
|
77
|
+
node: { tenantId: t1, scopeId: s1 },
|
|
78
|
+
expiresAt: at(HOUR),
|
|
79
|
+
grantedBy: alice,
|
|
80
|
+
});
|
|
81
|
+
await host.admin.grant(staff, {
|
|
82
|
+
principalId: eve,
|
|
83
|
+
permission: PERM_READ,
|
|
84
|
+
node: { tenantId: t1, scopeId: s1 },
|
|
85
|
+
entity: box,
|
|
86
|
+
expiresAt: at(HOUR),
|
|
87
|
+
grantedBy: alice,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
afterAll(async () => {
|
|
91
|
+
await fixture.cleanup();
|
|
92
|
+
});
|
|
93
|
+
it('a node-level grant is live before its expiresAt', async () => {
|
|
94
|
+
expect(await probe(nora, PERM_READ)).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
it('an entity-narrowed grant is live before its expiresAt', async () => {
|
|
97
|
+
expect(await probe(eve, PERM_READ, box)).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* The transition the wall clock cannot show. Nothing is revoked and nothing is
|
|
101
|
+
* swept: the only thing that changes is what time the host thinks it is.
|
|
102
|
+
*/
|
|
103
|
+
it('the node-level grant stops granting once the clock passes expiresAt', async () => {
|
|
104
|
+
clock.set(at(HOUR + 60_000));
|
|
105
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
it('the entity-narrowed grant stops granting once the clock passes expiresAt', async () => {
|
|
108
|
+
clock.set(at(HOUR + 60_000));
|
|
109
|
+
expect(await probe(eve, PERM_READ, box)).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* The boundary is part of the contract, not an adapter detail: the predicate is
|
|
113
|
+
* `expires_at > now`, so at the expiry instant itself the grant is already gone.
|
|
114
|
+
* A `>=` would pass every other test in this suite and silently widen every
|
|
115
|
+
* timed grant on that adapter by one instant — so the suite pins both sides of
|
|
116
|
+
* the line, for both shapes of grant.
|
|
117
|
+
*/
|
|
118
|
+
it('is gone at the expiry instant itself, not one past it', async () => {
|
|
119
|
+
clock.set(at(HOUR - 1));
|
|
120
|
+
expect(await probe(nora, PERM_READ)).toBe(true);
|
|
121
|
+
expect(await probe(eve, PERM_READ, box)).toBe(true);
|
|
122
|
+
clock.set(at(HOUR));
|
|
123
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
124
|
+
expect(await probe(eve, PERM_READ, box)).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
/**
|
|
127
|
+
* Expiry is judged on every check, not cached at grant time — so the same
|
|
128
|
+
* grant reads as live again if the clock is moved back before it. This is
|
|
129
|
+
* what distinguishes "the checker consults the clock" from "the grant was
|
|
130
|
+
* tombstoned when the clock passed it". The case sets up its own expiry first
|
|
131
|
+
* rather than inheriting the clock an earlier case left behind, so it proves
|
|
132
|
+
* the rollback when run alone too.
|
|
133
|
+
*/
|
|
134
|
+
it('is judged at check time — the same grant is live again with the clock before expiresAt', async () => {
|
|
135
|
+
clock.set(at(HOUR + 60_000));
|
|
136
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
137
|
+
expect(await probe(eve, PERM_READ, box)).toBe(false);
|
|
138
|
+
clock.set(at(HOUR - 60_000));
|
|
139
|
+
expect(await probe(nora, PERM_READ)).toBe(true);
|
|
140
|
+
expect(await probe(eve, PERM_READ, box)).toBe(true);
|
|
141
|
+
clock.set(at(HOUR + 60_000));
|
|
142
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
143
|
+
expect(await probe(eve, PERM_READ, box)).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Expiry is not sticky: a later re-grant of the same (principal, permission,
|
|
147
|
+
* node) carries its own `expiresAt`, and the checker judges that one. How the
|
|
148
|
+
* adapter stores it is its own business — the SQLite host keys tuples on
|
|
149
|
+
* (subject, relation, object) and the re-grant REPLACES the expired row, so
|
|
150
|
+
* there is never a dead row beside a live one there. What the contract holds is
|
|
151
|
+
* only the outcome: the expired grant does not shadow the new one, and the new
|
|
152
|
+
* one dies on its own clock.
|
|
153
|
+
*/
|
|
154
|
+
it('a re-grant after expiry grants again, on its own expiresAt', async () => {
|
|
155
|
+
clock.set(at(HOUR + 60_000));
|
|
156
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
157
|
+
await host.admin.grant(staff, {
|
|
158
|
+
principalId: nora,
|
|
159
|
+
permission: PERM_READ,
|
|
160
|
+
node: { tenantId: t1, scopeId: s1 },
|
|
161
|
+
expiresAt: at(3 * HOUR),
|
|
162
|
+
grantedBy: alice,
|
|
163
|
+
});
|
|
164
|
+
expect(await probe(nora, PERM_READ)).toBe(true);
|
|
165
|
+
clock.set(at(3 * HOUR + 60_000));
|
|
166
|
+
expect(await probe(nora, PERM_READ)).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
/** An untimed grant is unaffected by any clock — the control for the whole suite. */
|
|
169
|
+
it('a grant with no expiresAt is not touched by the clock', async () => {
|
|
170
|
+
await host.admin.grant(staff, {
|
|
171
|
+
principalId: nora,
|
|
172
|
+
permission: PERM_USE,
|
|
173
|
+
node: { tenantId: t1, scopeId: s1 },
|
|
174
|
+
grantedBy: alice,
|
|
175
|
+
});
|
|
176
|
+
clock.set(at(365 * 24 * HOUR));
|
|
177
|
+
expect(await probe(nora, PERM_USE)).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=grant-expiry-suite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant-expiry-suite.js","sourceRoot":"","sources":["../src/grant-expiry-suite.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,12 +12,14 @@ export { listContractSuite } from './list-suite.js';
|
|
|
12
12
|
export { scheduleContractSuite } from './schedule-suite.js';
|
|
13
13
|
export { inputParseContractSuite } from './input-parse-suite.js';
|
|
14
14
|
export { spineGuardContractSuite } from './spine-guard-suite.js';
|
|
15
|
+
export { grantExpiryContractSuite } from './grant-expiry-suite.js';
|
|
16
|
+
export type { GrantExpiryFixture } from './grant-expiry-suite.js';
|
|
15
17
|
export { entityCheckConformanceSuite, planEntityCheckCoverage } from './entity-check-suite.js';
|
|
16
18
|
export type { EntityCheckFixture, EntityCheckSuiteOptions, PlannedCheck } from './entity-check-suite.js';
|
|
17
19
|
export { nodeOnlySuite, declaredNodeOnlySuite } from './node-only-suite.js';
|
|
18
20
|
export type { NodeOnlyOptions } from './node-only-suite.js';
|
|
19
21
|
export { declareEntityChecks, declareNodeOnly, assertNodeOnly } from './conformance.js';
|
|
20
22
|
export type { ConformanceDeclaration, DrivenConformance, DeclaredNodeOnlyConformance, AssertedNodeOnlyConformance, } from './conformance.js';
|
|
21
|
-
export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, permMod, scheduleMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
|
|
23
|
+
export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, permMod, scheduleMod, freshnessMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
|
|
22
24
|
export { connectorCalls, connectorTestFetch, resetConnectorCalls, type ConnectorCall, } from './connector-fixture.js';
|
|
23
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,9 +11,10 @@ export { listContractSuite } from './list-suite.js';
|
|
|
11
11
|
export { scheduleContractSuite } from './schedule-suite.js';
|
|
12
12
|
export { inputParseContractSuite } from './input-parse-suite.js';
|
|
13
13
|
export { spineGuardContractSuite } from './spine-guard-suite.js';
|
|
14
|
+
export { grantExpiryContractSuite } from './grant-expiry-suite.js';
|
|
14
15
|
export { entityCheckConformanceSuite, planEntityCheckCoverage } from './entity-check-suite.js';
|
|
15
16
|
export { nodeOnlySuite, declaredNodeOnlySuite } from './node-only-suite.js';
|
|
16
17
|
export { declareEntityChecks, declareNodeOnly, assertNodeOnly } from './conformance.js';
|
|
17
|
-
export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, permMod, scheduleMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
|
|
18
|
+
export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, permMod, scheduleMod, freshnessMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
|
|
18
19
|
export { connectorCalls, connectorTestFetch, resetConnectorCalls, } from './connector-fixture.js';
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOxF,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOxF,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,wBAAwB,CAAC"}
|
package/dist/modules.d.ts
CHANGED
|
@@ -53,6 +53,12 @@ export declare const testModManifest: {
|
|
|
53
53
|
input?: Record<string, unknown> | undefined;
|
|
54
54
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
55
55
|
}[] | undefined;
|
|
56
|
+
freshness?: {
|
|
57
|
+
eventType: string;
|
|
58
|
+
within: {
|
|
59
|
+
hours: number;
|
|
60
|
+
};
|
|
61
|
+
}[] | undefined;
|
|
56
62
|
withdraws?: string[] | undefined;
|
|
57
63
|
entitlementKey: string;
|
|
58
64
|
envSpec?: {
|
|
@@ -156,6 +162,127 @@ export declare const scheduleModManifest: {
|
|
|
156
162
|
input?: Record<string, unknown> | undefined;
|
|
157
163
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
158
164
|
}[] | undefined;
|
|
165
|
+
freshness?: {
|
|
166
|
+
eventType: string;
|
|
167
|
+
within: {
|
|
168
|
+
hours: number;
|
|
169
|
+
};
|
|
170
|
+
}[] | undefined;
|
|
171
|
+
withdraws?: string[] | undefined;
|
|
172
|
+
entitlementKey: string;
|
|
173
|
+
envSpec?: {
|
|
174
|
+
key: string;
|
|
175
|
+
label?: string | undefined;
|
|
176
|
+
description: string;
|
|
177
|
+
placeholder?: string | undefined;
|
|
178
|
+
required: boolean;
|
|
179
|
+
secret: boolean;
|
|
180
|
+
default?: string | undefined;
|
|
181
|
+
group?: string | undefined;
|
|
182
|
+
}[] | undefined;
|
|
183
|
+
ownerGrants?: (string & z.$brand<"PermissionKey">)[] | undefined;
|
|
184
|
+
entitlements?: string[] | undefined;
|
|
185
|
+
provides?: string[] | undefined;
|
|
186
|
+
requires?: string[] | undefined;
|
|
187
|
+
api?: string | undefined;
|
|
188
|
+
searchables?: {
|
|
189
|
+
entityType: string;
|
|
190
|
+
fields: string[];
|
|
191
|
+
table?: string | undefined;
|
|
192
|
+
idColumn?: string | undefined;
|
|
193
|
+
tokenizer?: "prefix" | "substring" | undefined;
|
|
194
|
+
}[] | undefined;
|
|
195
|
+
lists?: {
|
|
196
|
+
entityType: string;
|
|
197
|
+
sortable: string[];
|
|
198
|
+
filterable?: string[] | undefined;
|
|
199
|
+
table?: string | undefined;
|
|
200
|
+
idColumn?: string | undefined;
|
|
201
|
+
}[] | undefined;
|
|
202
|
+
ui?: {
|
|
203
|
+
routes?: {
|
|
204
|
+
path: string;
|
|
205
|
+
screen: string;
|
|
206
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
207
|
+
}[] | undefined;
|
|
208
|
+
nav?: {
|
|
209
|
+
label: string;
|
|
210
|
+
icon?: string | undefined;
|
|
211
|
+
to: string;
|
|
212
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
213
|
+
}[] | undefined;
|
|
214
|
+
entityViews?: {
|
|
215
|
+
entityType: string;
|
|
216
|
+
view: string;
|
|
217
|
+
}[] | undefined;
|
|
218
|
+
widgets?: {
|
|
219
|
+
slot: string;
|
|
220
|
+
component: string;
|
|
221
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
222
|
+
}[] | undefined;
|
|
223
|
+
settingsPanels?: {
|
|
224
|
+
label: string;
|
|
225
|
+
component: string;
|
|
226
|
+
permission: string & z.$brand<"PermissionKey">;
|
|
227
|
+
}[] | undefined;
|
|
228
|
+
} | undefined;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* #1232 regression fixture: a SECOND module expecting the same event type as
|
|
232
|
+
* scheduleMod, with a WIDER window. The evaluator must aggregate across modules
|
|
233
|
+
* to the tightest window and evaluate once per scope — per-module evaluation
|
|
234
|
+
* would fight over the shared gating-state key and dedupe unit.
|
|
235
|
+
*/
|
|
236
|
+
export declare const freshnessModManifest: {
|
|
237
|
+
id: string & z.$brand<"ModuleId">;
|
|
238
|
+
version: string;
|
|
239
|
+
kernelContract: string;
|
|
240
|
+
permissions: {
|
|
241
|
+
key: string & z.$brand<"PermissionKey">;
|
|
242
|
+
description: string;
|
|
243
|
+
}[];
|
|
244
|
+
events: {
|
|
245
|
+
emits: {
|
|
246
|
+
type: string;
|
|
247
|
+
schemaVersion: number;
|
|
248
|
+
}[];
|
|
249
|
+
consumes: {
|
|
250
|
+
type: string;
|
|
251
|
+
schemaVersion: number;
|
|
252
|
+
}[];
|
|
253
|
+
};
|
|
254
|
+
migrations: {
|
|
255
|
+
journalDir: string;
|
|
256
|
+
compatibleFrom: string;
|
|
257
|
+
};
|
|
258
|
+
attachmentTargets: {
|
|
259
|
+
entityType: string;
|
|
260
|
+
readPermission: string & z.$brand<"PermissionKey">;
|
|
261
|
+
writePermission?: (string & z.$brand<"PermissionKey">) | undefined;
|
|
262
|
+
}[];
|
|
263
|
+
entityRelations?: {
|
|
264
|
+
entityType: string;
|
|
265
|
+
parentType: string;
|
|
266
|
+
}[] | undefined;
|
|
267
|
+
guards?: {
|
|
268
|
+
before: string;
|
|
269
|
+
predicate: string;
|
|
270
|
+
config: Record<string, unknown>;
|
|
271
|
+
}[] | undefined;
|
|
272
|
+
schedules?: {
|
|
273
|
+
operation: string;
|
|
274
|
+
cadence: {
|
|
275
|
+
everyMinutes: number;
|
|
276
|
+
};
|
|
277
|
+
input?: Record<string, unknown> | undefined;
|
|
278
|
+
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
279
|
+
}[] | undefined;
|
|
280
|
+
freshness?: {
|
|
281
|
+
eventType: string;
|
|
282
|
+
within: {
|
|
283
|
+
hours: number;
|
|
284
|
+
};
|
|
285
|
+
}[] | undefined;
|
|
159
286
|
withdraws?: string[] | undefined;
|
|
160
287
|
entitlementKey: string;
|
|
161
288
|
envSpec?: {
|
|
@@ -215,6 +342,7 @@ export declare const scheduleModManifest: {
|
|
|
215
342
|
}[] | undefined;
|
|
216
343
|
} | undefined;
|
|
217
344
|
};
|
|
345
|
+
export declare const freshnessMod: ModuleRegistration;
|
|
218
346
|
export declare const flowModManifest: {
|
|
219
347
|
id: string & z.$brand<"ModuleId">;
|
|
220
348
|
version: string;
|
|
@@ -259,6 +387,12 @@ export declare const flowModManifest: {
|
|
|
259
387
|
input?: Record<string, unknown> | undefined;
|
|
260
388
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
261
389
|
}[] | undefined;
|
|
390
|
+
freshness?: {
|
|
391
|
+
eventType: string;
|
|
392
|
+
within: {
|
|
393
|
+
hours: number;
|
|
394
|
+
};
|
|
395
|
+
}[] | undefined;
|
|
262
396
|
withdraws?: string[] | undefined;
|
|
263
397
|
entitlementKey: string;
|
|
264
398
|
envSpec?: {
|
|
@@ -362,6 +496,12 @@ export declare const atomicModManifest: {
|
|
|
362
496
|
input?: Record<string, unknown> | undefined;
|
|
363
497
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
364
498
|
}[] | undefined;
|
|
499
|
+
freshness?: {
|
|
500
|
+
eventType: string;
|
|
501
|
+
within: {
|
|
502
|
+
hours: number;
|
|
503
|
+
};
|
|
504
|
+
}[] | undefined;
|
|
365
505
|
withdraws?: string[] | undefined;
|
|
366
506
|
entitlementKey: string;
|
|
367
507
|
envSpec?: {
|
|
@@ -465,6 +605,12 @@ export declare const lateModManifest: {
|
|
|
465
605
|
input?: Record<string, unknown> | undefined;
|
|
466
606
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
467
607
|
}[] | undefined;
|
|
608
|
+
freshness?: {
|
|
609
|
+
eventType: string;
|
|
610
|
+
within: {
|
|
611
|
+
hours: number;
|
|
612
|
+
};
|
|
613
|
+
}[] | undefined;
|
|
468
614
|
withdraws?: string[] | undefined;
|
|
469
615
|
entitlementKey: string;
|
|
470
616
|
envSpec?: {
|
|
@@ -568,6 +714,12 @@ export declare const billedModManifest: {
|
|
|
568
714
|
input?: Record<string, unknown> | undefined;
|
|
569
715
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
570
716
|
}[] | undefined;
|
|
717
|
+
freshness?: {
|
|
718
|
+
eventType: string;
|
|
719
|
+
within: {
|
|
720
|
+
hours: number;
|
|
721
|
+
};
|
|
722
|
+
}[] | undefined;
|
|
571
723
|
withdraws?: string[] | undefined;
|
|
572
724
|
entitlementKey: string;
|
|
573
725
|
envSpec?: {
|
|
@@ -671,6 +823,12 @@ export declare const guardedModManifest: {
|
|
|
671
823
|
input?: Record<string, unknown> | undefined;
|
|
672
824
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
673
825
|
}[] | undefined;
|
|
826
|
+
freshness?: {
|
|
827
|
+
eventType: string;
|
|
828
|
+
within: {
|
|
829
|
+
hours: number;
|
|
830
|
+
};
|
|
831
|
+
}[] | undefined;
|
|
674
832
|
withdraws?: string[] | undefined;
|
|
675
833
|
entitlementKey: string;
|
|
676
834
|
envSpec?: {
|
|
@@ -774,6 +932,12 @@ export declare const withdrawEarlyManifest: {
|
|
|
774
932
|
input?: Record<string, unknown> | undefined;
|
|
775
933
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
776
934
|
}[] | undefined;
|
|
935
|
+
freshness?: {
|
|
936
|
+
eventType: string;
|
|
937
|
+
within: {
|
|
938
|
+
hours: number;
|
|
939
|
+
};
|
|
940
|
+
}[] | undefined;
|
|
777
941
|
withdraws?: string[] | undefined;
|
|
778
942
|
entitlementKey: string;
|
|
779
943
|
envSpec?: {
|
|
@@ -877,6 +1041,12 @@ export declare const victimModManifest: {
|
|
|
877
1041
|
input?: Record<string, unknown> | undefined;
|
|
878
1042
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
879
1043
|
}[] | undefined;
|
|
1044
|
+
freshness?: {
|
|
1045
|
+
eventType: string;
|
|
1046
|
+
within: {
|
|
1047
|
+
hours: number;
|
|
1048
|
+
};
|
|
1049
|
+
}[] | undefined;
|
|
880
1050
|
withdraws?: string[] | undefined;
|
|
881
1051
|
entitlementKey: string;
|
|
882
1052
|
envSpec?: {
|
|
@@ -980,6 +1150,12 @@ export declare const withdrawLateManifest: {
|
|
|
980
1150
|
input?: Record<string, unknown> | undefined;
|
|
981
1151
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
982
1152
|
}[] | undefined;
|
|
1153
|
+
freshness?: {
|
|
1154
|
+
eventType: string;
|
|
1155
|
+
within: {
|
|
1156
|
+
hours: number;
|
|
1157
|
+
};
|
|
1158
|
+
}[] | undefined;
|
|
983
1159
|
withdraws?: string[] | undefined;
|
|
984
1160
|
entitlementKey: string;
|
|
985
1161
|
envSpec?: {
|
|
@@ -1083,6 +1259,12 @@ export declare const gateModManifest: {
|
|
|
1083
1259
|
input?: Record<string, unknown> | undefined;
|
|
1084
1260
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1085
1261
|
}[] | undefined;
|
|
1262
|
+
freshness?: {
|
|
1263
|
+
eventType: string;
|
|
1264
|
+
within: {
|
|
1265
|
+
hours: number;
|
|
1266
|
+
};
|
|
1267
|
+
}[] | undefined;
|
|
1086
1268
|
withdraws?: string[] | undefined;
|
|
1087
1269
|
entitlementKey: string;
|
|
1088
1270
|
envSpec?: {
|
|
@@ -1195,6 +1377,12 @@ export declare const impersonationEchoManifest: {
|
|
|
1195
1377
|
input?: Record<string, unknown> | undefined;
|
|
1196
1378
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1197
1379
|
}[] | undefined;
|
|
1380
|
+
freshness?: {
|
|
1381
|
+
eventType: string;
|
|
1382
|
+
within: {
|
|
1383
|
+
hours: number;
|
|
1384
|
+
};
|
|
1385
|
+
}[] | undefined;
|
|
1198
1386
|
withdraws?: string[] | undefined;
|
|
1199
1387
|
entitlementKey: string;
|
|
1200
1388
|
envSpec?: {
|
|
@@ -1298,6 +1486,12 @@ export declare const permModManifest: {
|
|
|
1298
1486
|
input?: Record<string, unknown> | undefined;
|
|
1299
1487
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1300
1488
|
}[] | undefined;
|
|
1489
|
+
freshness?: {
|
|
1490
|
+
eventType: string;
|
|
1491
|
+
within: {
|
|
1492
|
+
hours: number;
|
|
1493
|
+
};
|
|
1494
|
+
}[] | undefined;
|
|
1301
1495
|
withdraws?: string[] | undefined;
|
|
1302
1496
|
entitlementKey: string;
|
|
1303
1497
|
envSpec?: {
|
|
@@ -1415,6 +1609,12 @@ export declare const connectorModManifest: {
|
|
|
1415
1609
|
input?: Record<string, unknown> | undefined;
|
|
1416
1610
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1417
1611
|
}[] | undefined;
|
|
1612
|
+
freshness?: {
|
|
1613
|
+
eventType: string;
|
|
1614
|
+
within: {
|
|
1615
|
+
hours: number;
|
|
1616
|
+
};
|
|
1617
|
+
}[] | undefined;
|
|
1418
1618
|
withdraws?: string[] | undefined;
|
|
1419
1619
|
entitlementKey: string;
|
|
1420
1620
|
envSpec?: {
|
|
@@ -1549,6 +1749,12 @@ export declare const listModManifest: {
|
|
|
1549
1749
|
input?: Record<string, unknown> | undefined;
|
|
1550
1750
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1551
1751
|
}[] | undefined;
|
|
1752
|
+
freshness?: {
|
|
1753
|
+
eventType: string;
|
|
1754
|
+
within: {
|
|
1755
|
+
hours: number;
|
|
1756
|
+
};
|
|
1757
|
+
}[] | undefined;
|
|
1552
1758
|
withdraws?: string[] | undefined;
|
|
1553
1759
|
entitlementKey: string;
|
|
1554
1760
|
envSpec?: {
|
|
@@ -1653,6 +1859,12 @@ export declare const searchModManifest: {
|
|
|
1653
1859
|
input?: Record<string, unknown> | undefined;
|
|
1654
1860
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1655
1861
|
}[] | undefined;
|
|
1862
|
+
freshness?: {
|
|
1863
|
+
eventType: string;
|
|
1864
|
+
within: {
|
|
1865
|
+
hours: number;
|
|
1866
|
+
};
|
|
1867
|
+
}[] | undefined;
|
|
1656
1868
|
withdraws?: string[] | undefined;
|
|
1657
1869
|
entitlementKey: string;
|
|
1658
1870
|
envSpec?: {
|
|
@@ -1757,6 +1969,12 @@ export declare const parseModManifest: {
|
|
|
1757
1969
|
input?: Record<string, unknown> | undefined;
|
|
1758
1970
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1759
1971
|
}[] | undefined;
|
|
1972
|
+
freshness?: {
|
|
1973
|
+
eventType: string;
|
|
1974
|
+
within: {
|
|
1975
|
+
hours: number;
|
|
1976
|
+
};
|
|
1977
|
+
}[] | undefined;
|
|
1760
1978
|
withdraws?: string[] | undefined;
|
|
1761
1979
|
entitlementKey: string;
|
|
1762
1980
|
envSpec?: {
|
|
@@ -1861,6 +2079,12 @@ export declare const concurrencyModManifest: {
|
|
|
1861
2079
|
input?: Record<string, unknown> | undefined;
|
|
1862
2080
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1863
2081
|
}[] | undefined;
|
|
2082
|
+
freshness?: {
|
|
2083
|
+
eventType: string;
|
|
2084
|
+
within: {
|
|
2085
|
+
hours: number;
|
|
2086
|
+
};
|
|
2087
|
+
}[] | undefined;
|
|
1864
2088
|
withdraws?: string[] | undefined;
|
|
1865
2089
|
entitlementKey: string;
|
|
1866
2090
|
envSpec?: {
|
|
@@ -1965,6 +2189,12 @@ export declare const idempotencyModManifest: {
|
|
|
1965
2189
|
input?: Record<string, unknown> | undefined;
|
|
1966
2190
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
1967
2191
|
}[] | undefined;
|
|
2192
|
+
freshness?: {
|
|
2193
|
+
eventType: string;
|
|
2194
|
+
within: {
|
|
2195
|
+
hours: number;
|
|
2196
|
+
};
|
|
2197
|
+
}[] | undefined;
|
|
1968
2198
|
withdraws?: string[] | undefined;
|
|
1969
2199
|
entitlementKey: string;
|
|
1970
2200
|
envSpec?: {
|
|
@@ -2070,6 +2300,12 @@ export declare const brokenModManifest: {
|
|
|
2070
2300
|
input?: Record<string, unknown> | undefined;
|
|
2071
2301
|
permissions: (string & z.$brand<"PermissionKey">)[];
|
|
2072
2302
|
}[] | undefined;
|
|
2303
|
+
freshness?: {
|
|
2304
|
+
eventType: string;
|
|
2305
|
+
within: {
|
|
2306
|
+
hours: number;
|
|
2307
|
+
};
|
|
2308
|
+
}[] | undefined;
|
|
2073
2309
|
withdraws?: string[] | undefined;
|
|
2074
2310
|
entitlementKey: string;
|
|
2075
2311
|
envSpec?: {
|