@adcp/sdk 15.3.0 → 15.5.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/dist/lib/advanced.d.mts +2 -2
- package/dist/lib/advanced.d.ts +2 -2
- package/dist/lib/advanced.js +8 -2
- package/dist/lib/advanced.mjs +8 -2
- package/dist/lib/core/AgentClient.d.mts +4 -0
- package/dist/lib/core/AgentClient.d.ts +4 -0
- package/dist/lib/core/AgentClient.js +8 -0
- package/dist/lib/core/AgentClient.mjs +8 -0
- package/dist/lib/core/SingleAgentClient.d.mts +154 -0
- package/dist/lib/core/SingleAgentClient.d.ts +154 -0
- package/dist/lib/core/SingleAgentClient.js +661 -23
- package/dist/lib/core/SingleAgentClient.mjs +666 -23
- package/dist/lib/core/agent-discovery-cache.d.mts +103 -0
- package/dist/lib/core/agent-discovery-cache.d.ts +103 -0
- package/dist/lib/core/agent-discovery-cache.js +121 -0
- package/dist/lib/core/agent-discovery-cache.mjs +92 -0
- package/dist/lib/index.d.mts +5 -3
- package/dist/lib/index.d.ts +5 -3
- package/dist/lib/index.js +7 -0
- package/dist/lib/index.mjs +6 -0
- package/dist/lib/protocols/index.d.mts +2 -2
- package/dist/lib/protocols/index.d.ts +2 -2
- package/dist/lib/protocols/index.js +1 -1
- package/dist/lib/protocols/index.mjs +1 -1
- package/dist/lib/protocols/mcp-call-context.d.mts +109 -0
- package/dist/lib/protocols/mcp-call-context.d.ts +109 -0
- package/dist/lib/protocols/mcp-call-context.js +221 -0
- package/dist/lib/protocols/mcp-call-context.mjs +186 -0
- package/dist/lib/protocols/mcp-modern.d.mts +9 -1
- package/dist/lib/protocols/mcp-modern.d.ts +9 -1
- package/dist/lib/protocols/mcp-modern.js +180 -104
- package/dist/lib/protocols/mcp-modern.mjs +193 -104
- package/dist/lib/protocols/mcp-scope.d.mts +15 -0
- package/dist/lib/protocols/mcp-scope.d.ts +15 -0
- package/dist/lib/protocols/mcp.d.mts +4 -2
- package/dist/lib/protocols/mcp.d.ts +4 -2
- package/dist/lib/protocols/mcp.js +178 -154
- package/dist/lib/protocols/mcp.mjs +189 -153
- package/dist/lib/protocols/transportDiagnostics.d.mts +33 -1
- package/dist/lib/protocols/transportDiagnostics.d.ts +33 -1
- package/dist/lib/protocols/transportDiagnostics.js +128 -12
- package/dist/lib/protocols/transportDiagnostics.mjs +128 -12
- package/dist/lib/reporting/gcs/index.d.mts +2 -0
- package/dist/lib/reporting/gcs/index.d.ts +2 -0
- package/dist/lib/reporting/gcs/index.js +3 -0
- package/dist/lib/reporting/gcs/index.mjs +2 -0
- package/dist/lib/reporting/gcs/row-provider.d.mts +32 -0
- package/dist/lib/reporting/gcs/row-provider.d.ts +32 -0
- package/dist/lib/reporting/gcs/row-provider.js +205 -0
- package/dist/lib/reporting/gcs/row-provider.mjs +188 -0
- package/dist/lib/reporting/ledger/change-feed.d.mts +41 -0
- package/dist/lib/reporting/ledger/change-feed.d.ts +41 -0
- package/dist/lib/reporting/ledger/change-feed.js +101 -0
- package/dist/lib/reporting/ledger/change-feed.mjs +74 -0
- package/dist/lib/reporting/ledger/handler.d.mts +6 -0
- package/dist/lib/reporting/ledger/handler.d.ts +6 -0
- package/dist/lib/reporting/ledger/handler.js +51 -8
- package/dist/lib/reporting/ledger/handler.mjs +50 -8
- package/dist/lib/reporting/ledger/index.d.mts +5 -0
- package/dist/lib/reporting/ledger/index.d.ts +5 -0
- package/dist/lib/reporting/ledger/index.js +11 -1
- package/dist/lib/reporting/ledger/index.mjs +5 -0
- package/dist/lib/reporting/ledger/lifecycle.js +3 -2
- package/dist/lib/reporting/ledger/lifecycle.mjs +3 -2
- package/dist/lib/reporting/ledger/managed-postgres.d.mts +2 -0
- package/dist/lib/reporting/ledger/managed-postgres.d.ts +2 -0
- package/dist/lib/reporting/ledger/managed-postgres.js +26 -6
- package/dist/lib/reporting/ledger/managed-postgres.mjs +26 -6
- package/dist/lib/reporting/ledger/managed.d.mts +9 -0
- package/dist/lib/reporting/ledger/managed.d.ts +9 -0
- package/dist/lib/reporting/ledger/managed.js +18 -0
- package/dist/lib/reporting/ledger/managed.mjs +18 -0
- package/dist/lib/reporting/ledger/postgres.d.mts +179 -1
- package/dist/lib/reporting/ledger/postgres.d.ts +179 -1
- package/dist/lib/reporting/ledger/postgres.js +882 -19
- package/dist/lib/reporting/ledger/postgres.mjs +890 -19
- package/dist/lib/reporting/ledger/producer.js +13 -3
- package/dist/lib/reporting/ledger/producer.mjs +13 -3
- package/dist/lib/reporting/ledger/revision-metadata.d.mts +17 -0
- package/dist/lib/reporting/ledger/revision-metadata.d.ts +17 -0
- package/dist/lib/reporting/ledger/revision-metadata.js +71 -0
- package/dist/lib/reporting/ledger/revision-metadata.mjs +44 -0
- package/dist/lib/reporting/ledger/row-encoding.d.mts +128 -0
- package/dist/lib/reporting/ledger/row-encoding.d.ts +128 -0
- package/dist/lib/reporting/ledger/row-encoding.js +355 -0
- package/dist/lib/reporting/ledger/row-encoding.mjs +315 -0
- package/dist/lib/reporting/ledger/row-storage-errors.d.mts +7 -0
- package/dist/lib/reporting/ledger/row-storage-errors.d.ts +7 -0
- package/dist/lib/reporting/ledger/row-storage-errors.js +41 -0
- package/dist/lib/reporting/ledger/row-storage-errors.mjs +16 -0
- package/dist/lib/reporting/ledger/row-storage-migration.d.mts +41 -0
- package/dist/lib/reporting/ledger/row-storage-migration.d.ts +41 -0
- package/dist/lib/reporting/ledger/row-storage-migration.js +234 -0
- package/dist/lib/reporting/ledger/row-storage-migration.mjs +208 -0
- package/dist/lib/reporting/ledger/row-storage-object.d.mts +112 -0
- package/dist/lib/reporting/ledger/row-storage-object.d.ts +112 -0
- package/dist/lib/reporting/ledger/row-storage-object.js +281 -0
- package/dist/lib/reporting/ledger/row-storage-object.mjs +239 -0
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +51 -0
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +51 -0
- package/dist/lib/reporting/ledger/row-storage-provider-io.js +152 -0
- package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +119 -0
- package/dist/lib/reporting/ledger/row-storage.d.mts +224 -0
- package/dist/lib/reporting/ledger/row-storage.d.ts +224 -0
- package/dist/lib/reporting/ledger/row-storage.js +692 -0
- package/dist/lib/reporting/ledger/row-storage.mjs +680 -0
- package/dist/lib/reporting/ledger/types.d.mts +45 -0
- package/dist/lib/reporting/ledger/types.d.ts +45 -0
- package/dist/lib/reporting/service/index.d.mts +41 -1
- package/dist/lib/reporting/service/index.d.ts +41 -1
- package/dist/lib/reporting/service/index.js +68 -1
- package/dist/lib/reporting/service/index.mjs +70 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.js +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/README.md +1 -1
- package/docs/TYPE-SUMMARY.md +35 -2
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +142 -0
- package/docs/guides/EXISTING-PLATFORM.md +43 -12
- package/docs/guides/REPORTING-LEDGER.md +209 -0
- package/docs/llms.txt +4 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/recipes/verifying-inbound-webhooks.md +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object-storage providers for revision row chunks (shared SDK persistence
|
|
3
|
+
* spec, adcontextprotocol/adcp#7996 §3.3–§3.4).
|
|
4
|
+
*
|
|
5
|
+
* A provider is a thin, credential-free port over one object store. It never
|
|
6
|
+
* decides where bytes go: keys are rendered by the SDK from an allowlisted
|
|
7
|
+
* binding, and every byte a provider returns is verified against digests
|
|
8
|
+
* committed in PostgreSQL before rows are released.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReportingRowObjectContextV1 {
|
|
11
|
+
signal: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
export interface ReportingRowObjectLocationV1 {
|
|
14
|
+
/** Non-secret provider coordinates (bucket, container, filesystem root name, endpoint host). */
|
|
15
|
+
readonly location: Readonly<Record<string, string>>;
|
|
16
|
+
/** Host-mapped client reference; never a secret. */
|
|
17
|
+
readonly credentialRef?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ReportingRowObjectPutInputV1 extends ReportingRowObjectLocationV1 {
|
|
20
|
+
key: string;
|
|
21
|
+
bytes: Uint8Array;
|
|
22
|
+
contentType: 'application/x-ndjson' | 'application/gzip';
|
|
23
|
+
/** Non-secret object metadata (installation and intent identifiers). */
|
|
24
|
+
metadata: Readonly<Record<string, string>>;
|
|
25
|
+
}
|
|
26
|
+
export interface ReportingRowObjectGetInputV1 extends ReportingRowObjectLocationV1 {
|
|
27
|
+
key: string;
|
|
28
|
+
/** Exact native version recorded at write time. */
|
|
29
|
+
nativeVersion: string;
|
|
30
|
+
/** Byte range within the stored object; omit for the whole object. */
|
|
31
|
+
range?: {
|
|
32
|
+
offset: number;
|
|
33
|
+
length: number;
|
|
34
|
+
};
|
|
35
|
+
/** Hard cap on bytes read; providers abort beyond it. */
|
|
36
|
+
maxBytes: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ReportingRowObjectDeleteInputV1 extends ReportingRowObjectLocationV1 {
|
|
39
|
+
key: string;
|
|
40
|
+
nativeVersion: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ReportingRowObjectProviderV1 {
|
|
43
|
+
/** Registry name, e.g. `filesystem`, `gcs`, `s3`, `azure_blob`. */
|
|
44
|
+
readonly name: string;
|
|
45
|
+
/** Whether `get` honours `range` without reading the whole object. */
|
|
46
|
+
readonly rangedReads: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Validate binding coordinates against the provider's closed schema. Throw
|
|
49
|
+
* `INVALID_INPUT` for unknown fields or values that could carry secrets.
|
|
50
|
+
*/
|
|
51
|
+
validateLocation(location: Readonly<Record<string, string>>): void;
|
|
52
|
+
/** Fail closed (`UNSAFE_BINDING`) when the destination is unsafe or create-only writes are not enforced. */
|
|
53
|
+
probe(input: ReportingRowObjectLocationV1 & {
|
|
54
|
+
prefix: string;
|
|
55
|
+
}, context: ReportingRowObjectContextV1): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Create-only write. Returns `created: true` with the new native version, or
|
|
58
|
+
* `created: false` with the existing object's version when the key is taken.
|
|
59
|
+
* Must never replace an existing object.
|
|
60
|
+
*/
|
|
61
|
+
putIfAbsent(input: ReportingRowObjectPutInputV1, context: ReportingRowObjectContextV1): Promise<{
|
|
62
|
+
created: boolean;
|
|
63
|
+
nativeVersion: string;
|
|
64
|
+
}>;
|
|
65
|
+
/** Bytes at the exact native version, or `null` when that version is absent. */
|
|
66
|
+
get(input: ReportingRowObjectGetInputV1, context: ReportingRowObjectContextV1): Promise<Uint8Array | null>;
|
|
67
|
+
/** Delete the exact native version. Idempotent: `absent` is success. */
|
|
68
|
+
delete(input: ReportingRowObjectDeleteInputV1, context: ReportingRowObjectContextV1): Promise<'deleted' | 'absent'>;
|
|
69
|
+
}
|
|
70
|
+
/** Placeholders allowed in object key templates. */
|
|
71
|
+
export declare const REPORTING_ROW_KEY_PLACEHOLDERS: readonly ["prefix", "namespace_key", "account_key", "period_date", "finality", "revision_key", "content_sha256", "chunk_index"];
|
|
72
|
+
export declare const REPORTING_ROW_DEFAULT_KEY_TEMPLATE = "{prefix}/{namespace_key}/{account_key}/{period_date}/{finality}/{revision_key}/{content_sha256}/{chunk_index}";
|
|
73
|
+
/** Validate an object key template; throws `INVALID_INPUT`. */
|
|
74
|
+
export declare function assertReportingRowKeyTemplateV1(template: string): void;
|
|
75
|
+
export declare function assertReportingRowPrefixV1(prefix: string): void;
|
|
76
|
+
/** Pseudonymous account segment; never a raw account ID. */
|
|
77
|
+
export declare function reportingRowAccountKeyV1(namespaceKey: string, accountId: string): string;
|
|
78
|
+
export declare function reportingRowRevisionKeyV1(rowSetId: string): string;
|
|
79
|
+
/** Render one chunk's object key and confine it to the binding's owned prefix. */
|
|
80
|
+
export declare function renderReportingRowObjectKeyV1(input: {
|
|
81
|
+
template: string;
|
|
82
|
+
prefix: string;
|
|
83
|
+
namespaceKey: string;
|
|
84
|
+
accountId: string;
|
|
85
|
+
rowSetId: string;
|
|
86
|
+
periodStart?: string;
|
|
87
|
+
finality?: 'snapshot' | 'official';
|
|
88
|
+
contentSha256: string;
|
|
89
|
+
chunkIndex: number;
|
|
90
|
+
compression: 'none' | 'gzip';
|
|
91
|
+
}): string;
|
|
92
|
+
export interface FilesystemReportingRowObjectProviderOptionsV1 {
|
|
93
|
+
/**
|
|
94
|
+
* Root name → absolute directory. Bindings name a root (`location.root`);
|
|
95
|
+
* they never carry paths, so the database cannot point writes elsewhere.
|
|
96
|
+
*/
|
|
97
|
+
roots: Readonly<Record<string, string>>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Local filesystem provider for tests and single-host deployments. Create-only
|
|
101
|
+
* writes use a temporary file, `fsync`, and `link()` to the final name, which
|
|
102
|
+
* fails rather than replacing an existing object.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createFilesystemReportingRowObjectProviderV1(options: FilesystemReportingRowObjectProviderOptionsV1): ReportingRowObjectProviderV1;
|
|
105
|
+
/**
|
|
106
|
+
* Behavioural conformance for a custom object provider. Writes and deletes
|
|
107
|
+
* only under `prefix`; run it against a dedicated test bucket or prefix.
|
|
108
|
+
* Resolves with the checks that passed; rejects on the first violation.
|
|
109
|
+
*/
|
|
110
|
+
export declare function runReportingRowObjectProviderConformanceV1(provider: ReportingRowObjectProviderV1, input: ReportingRowObjectLocationV1 & {
|
|
111
|
+
prefix: string;
|
|
112
|
+
}): Promise<string[]>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object-storage providers for revision row chunks (shared SDK persistence
|
|
3
|
+
* spec, adcontextprotocol/adcp#7996 §3.3–§3.4).
|
|
4
|
+
*
|
|
5
|
+
* A provider is a thin, credential-free port over one object store. It never
|
|
6
|
+
* decides where bytes go: keys are rendered by the SDK from an allowlisted
|
|
7
|
+
* binding, and every byte a provider returns is verified against digests
|
|
8
|
+
* committed in PostgreSQL before rows are released.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReportingRowObjectContextV1 {
|
|
11
|
+
signal: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
export interface ReportingRowObjectLocationV1 {
|
|
14
|
+
/** Non-secret provider coordinates (bucket, container, filesystem root name, endpoint host). */
|
|
15
|
+
readonly location: Readonly<Record<string, string>>;
|
|
16
|
+
/** Host-mapped client reference; never a secret. */
|
|
17
|
+
readonly credentialRef?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ReportingRowObjectPutInputV1 extends ReportingRowObjectLocationV1 {
|
|
20
|
+
key: string;
|
|
21
|
+
bytes: Uint8Array;
|
|
22
|
+
contentType: 'application/x-ndjson' | 'application/gzip';
|
|
23
|
+
/** Non-secret object metadata (installation and intent identifiers). */
|
|
24
|
+
metadata: Readonly<Record<string, string>>;
|
|
25
|
+
}
|
|
26
|
+
export interface ReportingRowObjectGetInputV1 extends ReportingRowObjectLocationV1 {
|
|
27
|
+
key: string;
|
|
28
|
+
/** Exact native version recorded at write time. */
|
|
29
|
+
nativeVersion: string;
|
|
30
|
+
/** Byte range within the stored object; omit for the whole object. */
|
|
31
|
+
range?: {
|
|
32
|
+
offset: number;
|
|
33
|
+
length: number;
|
|
34
|
+
};
|
|
35
|
+
/** Hard cap on bytes read; providers abort beyond it. */
|
|
36
|
+
maxBytes: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ReportingRowObjectDeleteInputV1 extends ReportingRowObjectLocationV1 {
|
|
39
|
+
key: string;
|
|
40
|
+
nativeVersion: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ReportingRowObjectProviderV1 {
|
|
43
|
+
/** Registry name, e.g. `filesystem`, `gcs`, `s3`, `azure_blob`. */
|
|
44
|
+
readonly name: string;
|
|
45
|
+
/** Whether `get` honours `range` without reading the whole object. */
|
|
46
|
+
readonly rangedReads: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Validate binding coordinates against the provider's closed schema. Throw
|
|
49
|
+
* `INVALID_INPUT` for unknown fields or values that could carry secrets.
|
|
50
|
+
*/
|
|
51
|
+
validateLocation(location: Readonly<Record<string, string>>): void;
|
|
52
|
+
/** Fail closed (`UNSAFE_BINDING`) when the destination is unsafe or create-only writes are not enforced. */
|
|
53
|
+
probe(input: ReportingRowObjectLocationV1 & {
|
|
54
|
+
prefix: string;
|
|
55
|
+
}, context: ReportingRowObjectContextV1): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Create-only write. Returns `created: true` with the new native version, or
|
|
58
|
+
* `created: false` with the existing object's version when the key is taken.
|
|
59
|
+
* Must never replace an existing object.
|
|
60
|
+
*/
|
|
61
|
+
putIfAbsent(input: ReportingRowObjectPutInputV1, context: ReportingRowObjectContextV1): Promise<{
|
|
62
|
+
created: boolean;
|
|
63
|
+
nativeVersion: string;
|
|
64
|
+
}>;
|
|
65
|
+
/** Bytes at the exact native version, or `null` when that version is absent. */
|
|
66
|
+
get(input: ReportingRowObjectGetInputV1, context: ReportingRowObjectContextV1): Promise<Uint8Array | null>;
|
|
67
|
+
/** Delete the exact native version. Idempotent: `absent` is success. */
|
|
68
|
+
delete(input: ReportingRowObjectDeleteInputV1, context: ReportingRowObjectContextV1): Promise<'deleted' | 'absent'>;
|
|
69
|
+
}
|
|
70
|
+
/** Placeholders allowed in object key templates. */
|
|
71
|
+
export declare const REPORTING_ROW_KEY_PLACEHOLDERS: readonly ["prefix", "namespace_key", "account_key", "period_date", "finality", "revision_key", "content_sha256", "chunk_index"];
|
|
72
|
+
export declare const REPORTING_ROW_DEFAULT_KEY_TEMPLATE = "{prefix}/{namespace_key}/{account_key}/{period_date}/{finality}/{revision_key}/{content_sha256}/{chunk_index}";
|
|
73
|
+
/** Validate an object key template; throws `INVALID_INPUT`. */
|
|
74
|
+
export declare function assertReportingRowKeyTemplateV1(template: string): void;
|
|
75
|
+
export declare function assertReportingRowPrefixV1(prefix: string): void;
|
|
76
|
+
/** Pseudonymous account segment; never a raw account ID. */
|
|
77
|
+
export declare function reportingRowAccountKeyV1(namespaceKey: string, accountId: string): string;
|
|
78
|
+
export declare function reportingRowRevisionKeyV1(rowSetId: string): string;
|
|
79
|
+
/** Render one chunk's object key and confine it to the binding's owned prefix. */
|
|
80
|
+
export declare function renderReportingRowObjectKeyV1(input: {
|
|
81
|
+
template: string;
|
|
82
|
+
prefix: string;
|
|
83
|
+
namespaceKey: string;
|
|
84
|
+
accountId: string;
|
|
85
|
+
rowSetId: string;
|
|
86
|
+
periodStart?: string;
|
|
87
|
+
finality?: 'snapshot' | 'official';
|
|
88
|
+
contentSha256: string;
|
|
89
|
+
chunkIndex: number;
|
|
90
|
+
compression: 'none' | 'gzip';
|
|
91
|
+
}): string;
|
|
92
|
+
export interface FilesystemReportingRowObjectProviderOptionsV1 {
|
|
93
|
+
/**
|
|
94
|
+
* Root name → absolute directory. Bindings name a root (`location.root`);
|
|
95
|
+
* they never carry paths, so the database cannot point writes elsewhere.
|
|
96
|
+
*/
|
|
97
|
+
roots: Readonly<Record<string, string>>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Local filesystem provider for tests and single-host deployments. Create-only
|
|
101
|
+
* writes use a temporary file, `fsync`, and `link()` to the final name, which
|
|
102
|
+
* fails rather than replacing an existing object.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createFilesystemReportingRowObjectProviderV1(options: FilesystemReportingRowObjectProviderOptionsV1): ReportingRowObjectProviderV1;
|
|
105
|
+
/**
|
|
106
|
+
* Behavioural conformance for a custom object provider. Writes and deletes
|
|
107
|
+
* only under `prefix`; run it against a dedicated test bucket or prefix.
|
|
108
|
+
* Resolves with the checks that passed; rejects on the first violation.
|
|
109
|
+
*/
|
|
110
|
+
export declare function runReportingRowObjectProviderConformanceV1(provider: ReportingRowObjectProviderV1, input: ReportingRowObjectLocationV1 & {
|
|
111
|
+
prefix: string;
|
|
112
|
+
}): Promise<string[]>;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var row_storage_object_exports = {};
|
|
30
|
+
__export(row_storage_object_exports, {
|
|
31
|
+
REPORTING_ROW_DEFAULT_KEY_TEMPLATE: () => REPORTING_ROW_DEFAULT_KEY_TEMPLATE,
|
|
32
|
+
REPORTING_ROW_KEY_PLACEHOLDERS: () => REPORTING_ROW_KEY_PLACEHOLDERS,
|
|
33
|
+
assertReportingRowKeyTemplateV1: () => assertReportingRowKeyTemplateV1,
|
|
34
|
+
assertReportingRowPrefixV1: () => assertReportingRowPrefixV1,
|
|
35
|
+
createFilesystemReportingRowObjectProviderV1: () => createFilesystemReportingRowObjectProviderV1,
|
|
36
|
+
renderReportingRowObjectKeyV1: () => renderReportingRowObjectKeyV1,
|
|
37
|
+
reportingRowAccountKeyV1: () => reportingRowAccountKeyV1,
|
|
38
|
+
reportingRowRevisionKeyV1: () => reportingRowRevisionKeyV1,
|
|
39
|
+
runReportingRowObjectProviderConformanceV1: () => runReportingRowObjectProviderConformanceV1
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(row_storage_object_exports);
|
|
42
|
+
var import_crypto = require("crypto");
|
|
43
|
+
var import_fs = require("fs");
|
|
44
|
+
var path = __toESM(require("path"));
|
|
45
|
+
var import_jcs = require('../../utils/jcs.js');
|
|
46
|
+
var import_row_storage_errors = require('./row-storage-errors.js');
|
|
47
|
+
const REPORTING_ROW_KEY_PLACEHOLDERS = Object.freeze([
|
|
48
|
+
"prefix",
|
|
49
|
+
"namespace_key",
|
|
50
|
+
"account_key",
|
|
51
|
+
"period_date",
|
|
52
|
+
"finality",
|
|
53
|
+
"revision_key",
|
|
54
|
+
"content_sha256",
|
|
55
|
+
"chunk_index"
|
|
56
|
+
]);
|
|
57
|
+
const REPORTING_ROW_DEFAULT_KEY_TEMPLATE = "{prefix}/{namespace_key}/{account_key}/{period_date}/{finality}/{revision_key}/{content_sha256}/{chunk_index}";
|
|
58
|
+
const PREFIX = /^[A-Za-z0-9_.=-]+(?:\/[A-Za-z0-9_.=-]+)*$/;
|
|
59
|
+
const KEY = /^[A-Za-z0-9_.=-]+(?:\/[A-Za-z0-9_.=-]+)*$/;
|
|
60
|
+
const PLACEHOLDER = /\{([a-z0-9_]+)\}/g;
|
|
61
|
+
function assertReportingRowKeyTemplateV1(template) {
|
|
62
|
+
if (!template.startsWith("{prefix}/{namespace_key}/")) {
|
|
63
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "key templates must begin with {prefix}/{namespace_key}/");
|
|
64
|
+
}
|
|
65
|
+
for (const required of ["{content_sha256}", "{chunk_index}"]) {
|
|
66
|
+
if (!template.includes(required)) {
|
|
67
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", `key templates must include ${required}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const unknown = [...template.matchAll(PLACEHOLDER)].map((match) => match[1]).filter((name) => !REPORTING_ROW_KEY_PLACEHOLDERS.includes(name));
|
|
71
|
+
if (unknown.length > 0) {
|
|
72
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", `unknown key template placeholders: ${unknown.join(", ")}`);
|
|
73
|
+
}
|
|
74
|
+
const literal = template.replace(PLACEHOLDER, "x");
|
|
75
|
+
if (!KEY.test(literal) || literal.split("/").some((segment) => segment === "." || segment === "..")) {
|
|
76
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "key template contains unsafe characters or segments");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function assertReportingRowPrefixV1(prefix) {
|
|
80
|
+
if (!PREFIX.test(prefix) || prefix.length > 512 || prefix.split("/").some((segment) => segment === "." || segment === "..")) {
|
|
81
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "row binding prefix is invalid");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function reportingRowAccountKeyV1(namespaceKey, accountId) {
|
|
85
|
+
return sha256Hex((0, import_jcs.canonicalize)(["adcp.account_key.v1", namespaceKey, accountId]));
|
|
86
|
+
}
|
|
87
|
+
function reportingRowRevisionKeyV1(rowSetId) {
|
|
88
|
+
return sha256Hex((0, import_jcs.canonicalize)(["adcp.revision_key.v1", rowSetId]));
|
|
89
|
+
}
|
|
90
|
+
function renderReportingRowObjectKeyV1(input) {
|
|
91
|
+
const values = {
|
|
92
|
+
prefix: input.prefix,
|
|
93
|
+
namespace_key: input.namespaceKey,
|
|
94
|
+
account_key: reportingRowAccountKeyV1(input.namespaceKey, input.accountId),
|
|
95
|
+
period_date: periodDate(input.periodStart),
|
|
96
|
+
finality: input.finality ?? "adjustment",
|
|
97
|
+
revision_key: reportingRowRevisionKeyV1(input.rowSetId),
|
|
98
|
+
content_sha256: input.contentSha256,
|
|
99
|
+
chunk_index: String(input.chunkIndex).padStart(6, "0")
|
|
100
|
+
};
|
|
101
|
+
const key = input.template.replace(PLACEHOLDER, (_, name) => values[name]) + (input.compression === "gzip" ? ".jsonl.gz" : ".jsonl");
|
|
102
|
+
if (!KEY.test(key) || key.split("/").some((segment) => segment === "." || segment === "..") || !key.startsWith(`${input.prefix}/${input.namespaceKey}/`)) {
|
|
103
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "rendered object key escapes the binding prefix");
|
|
104
|
+
}
|
|
105
|
+
return key;
|
|
106
|
+
}
|
|
107
|
+
function periodDate(periodStart) {
|
|
108
|
+
if (!periodStart) return "undated";
|
|
109
|
+
const parsed = new Date(periodStart);
|
|
110
|
+
if (Number.isNaN(parsed.getTime())) return "undated";
|
|
111
|
+
return parsed.toISOString().slice(0, 10).replace(/-/g, "/");
|
|
112
|
+
}
|
|
113
|
+
function createFilesystemReportingRowObjectProviderV1(options) {
|
|
114
|
+
const roots = /* @__PURE__ */ new Map();
|
|
115
|
+
for (const [name, directory] of Object.entries(options.roots)) {
|
|
116
|
+
if (!/^[A-Za-z0-9_.-]{1,64}$/.test(name) || !path.isAbsolute(directory)) {
|
|
117
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "filesystem roots need a simple name and an absolute path");
|
|
118
|
+
}
|
|
119
|
+
roots.set(name, path.resolve(directory));
|
|
120
|
+
}
|
|
121
|
+
const resolve = (location, key) => {
|
|
122
|
+
const root = roots.get(location.root ?? "");
|
|
123
|
+
if (!root) throw new import_row_storage_errors.ReportingRowStoreError("UNSAFE_BINDING", "filesystem root is not configured");
|
|
124
|
+
const target = path.resolve(root, key);
|
|
125
|
+
if (!target.startsWith(root + path.sep)) {
|
|
126
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "object key escapes the filesystem root");
|
|
127
|
+
}
|
|
128
|
+
return target;
|
|
129
|
+
};
|
|
130
|
+
const version = async (target) => {
|
|
131
|
+
const stat = await import_fs.promises.stat(target);
|
|
132
|
+
return `${stat.ino}:${stat.mtimeMs}:${stat.size}`;
|
|
133
|
+
};
|
|
134
|
+
return {
|
|
135
|
+
name: "filesystem",
|
|
136
|
+
rangedReads: true,
|
|
137
|
+
validateLocation(location) {
|
|
138
|
+
const keys = Object.keys(location);
|
|
139
|
+
if (keys.length !== 1 || keys[0] !== "root" || !roots.has(location.root)) {
|
|
140
|
+
throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "filesystem locations name exactly one configured root");
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
async probe(input) {
|
|
144
|
+
const root = roots.get(input.location.root ?? "");
|
|
145
|
+
if (!root) throw new import_row_storage_errors.ReportingRowStoreError("UNSAFE_BINDING", "filesystem root is not configured");
|
|
146
|
+
await import_fs.promises.mkdir(root, { recursive: true });
|
|
147
|
+
},
|
|
148
|
+
async putIfAbsent(input, context) {
|
|
149
|
+
context.signal.throwIfAborted();
|
|
150
|
+
const target = resolve(input.location, input.key);
|
|
151
|
+
await import_fs.promises.mkdir(path.dirname(target), { recursive: true });
|
|
152
|
+
const temporary = `${target}.${(0, import_crypto.randomUUID)()}.tmp`;
|
|
153
|
+
const handle = await import_fs.promises.open(temporary, "wx");
|
|
154
|
+
try {
|
|
155
|
+
await handle.writeFile(input.bytes);
|
|
156
|
+
await handle.sync();
|
|
157
|
+
} finally {
|
|
158
|
+
await handle.close();
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
await import_fs.promises.link(temporary, target);
|
|
162
|
+
return { created: true, nativeVersion: await version(target) };
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (error.code === "EEXIST") {
|
|
165
|
+
return { created: false, nativeVersion: await version(target) };
|
|
166
|
+
}
|
|
167
|
+
throw new import_row_storage_errors.ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem write failed");
|
|
168
|
+
} finally {
|
|
169
|
+
await import_fs.promises.rm(temporary, { force: true });
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
async get(input, context) {
|
|
173
|
+
context.signal.throwIfAborted();
|
|
174
|
+
const target = resolve(input.location, input.key);
|
|
175
|
+
let handle;
|
|
176
|
+
try {
|
|
177
|
+
handle = await import_fs.promises.open(target, "r");
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (error.code === "ENOENT") return null;
|
|
180
|
+
throw new import_row_storage_errors.ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem read failed");
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
const stat = await handle.stat();
|
|
184
|
+
if (`${stat.ino}:${stat.mtimeMs}:${stat.size}` !== input.nativeVersion) return null;
|
|
185
|
+
const offset = input.range?.offset ?? 0;
|
|
186
|
+
const length = input.range?.length ?? stat.size - offset;
|
|
187
|
+
if (offset < 0 || length < 0 || offset + length > stat.size) {
|
|
188
|
+
throw new import_row_storage_errors.ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "requested range exceeds the stored object");
|
|
189
|
+
}
|
|
190
|
+
if (length > input.maxBytes) {
|
|
191
|
+
throw new import_row_storage_errors.ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "stored object exceeds its recorded size");
|
|
192
|
+
}
|
|
193
|
+
const buffer = Buffer.alloc(length);
|
|
194
|
+
await handle.read(buffer, 0, length, offset);
|
|
195
|
+
return buffer;
|
|
196
|
+
} finally {
|
|
197
|
+
await handle.close();
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
async delete(input, context) {
|
|
201
|
+
context.signal.throwIfAborted();
|
|
202
|
+
const target = resolve(input.location, input.key);
|
|
203
|
+
try {
|
|
204
|
+
if (await version(target) !== input.nativeVersion) return "absent";
|
|
205
|
+
await import_fs.promises.unlink(target);
|
|
206
|
+
return "deleted";
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (error.code === "ENOENT") return "absent";
|
|
209
|
+
throw new import_row_storage_errors.ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem delete failed");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async function runReportingRowObjectProviderConformanceV1(provider, input) {
|
|
215
|
+
assertReportingRowPrefixV1(input.prefix);
|
|
216
|
+
provider.validateLocation(input.location);
|
|
217
|
+
const context = { signal: AbortSignal.timeout(6e4) };
|
|
218
|
+
const passed = [];
|
|
219
|
+
const key = `${input.prefix}/conformance/${(0, import_crypto.randomUUID)()}.jsonl`;
|
|
220
|
+
const first = Buffer.from('{"a":1}\n{"b":2}\n');
|
|
221
|
+
const metadata = { "adcp-installation": "conformance", "adcp-intent": "conformance" };
|
|
222
|
+
const base = { location: input.location, ...input.credentialRef ? { credentialRef: input.credentialRef } : {} };
|
|
223
|
+
await provider.probe(input, context);
|
|
224
|
+
passed.push("probe");
|
|
225
|
+
const created = await provider.putIfAbsent(
|
|
226
|
+
{ ...base, key, bytes: first, contentType: "application/x-ndjson", metadata },
|
|
227
|
+
context
|
|
228
|
+
);
|
|
229
|
+
if (!created.created || !created.nativeVersion) throw new Error("putIfAbsent did not create a new object");
|
|
230
|
+
passed.push("create");
|
|
231
|
+
const conflict = await provider.putIfAbsent(
|
|
232
|
+
{ ...base, key, bytes: Buffer.from('{"c":3}\n'), contentType: "application/x-ndjson", metadata },
|
|
233
|
+
context
|
|
234
|
+
);
|
|
235
|
+
if (conflict.created || conflict.nativeVersion !== created.nativeVersion) {
|
|
236
|
+
throw new Error("putIfAbsent replaced or re-versioned an existing object");
|
|
237
|
+
}
|
|
238
|
+
const stored = await provider.get({ ...base, key, nativeVersion: created.nativeVersion, maxBytes: 1024 }, context);
|
|
239
|
+
if (!stored || !Buffer.from(stored).equals(first))
|
|
240
|
+
throw new Error("create-only write did not preserve the first bytes");
|
|
241
|
+
passed.push("create-only");
|
|
242
|
+
if (provider.rangedReads) {
|
|
243
|
+
const ranged = await provider.get(
|
|
244
|
+
{ ...base, key, nativeVersion: created.nativeVersion, range: { offset: 8, length: 8 }, maxBytes: 1024 },
|
|
245
|
+
context
|
|
246
|
+
);
|
|
247
|
+
if (!ranged || Buffer.from(ranged).toString("utf8") !== '{"b":2}\n')
|
|
248
|
+
throw new Error("ranged read returned wrong bytes");
|
|
249
|
+
passed.push("ranged-read");
|
|
250
|
+
}
|
|
251
|
+
if (await provider.get({ ...base, key, nativeVersion: "not-a-version", maxBytes: 1024 }, context) !== null) {
|
|
252
|
+
throw new Error("get returned bytes for a version that does not exist");
|
|
253
|
+
}
|
|
254
|
+
passed.push("version-pinned-read");
|
|
255
|
+
if (await provider.delete({ ...base, key, nativeVersion: "not-a-version" }, context) !== "absent") {
|
|
256
|
+
throw new Error("delete removed an object at a different version");
|
|
257
|
+
}
|
|
258
|
+
if (await provider.delete({ ...base, key, nativeVersion: created.nativeVersion }, context) !== "deleted") {
|
|
259
|
+
throw new Error("delete did not remove the exact version");
|
|
260
|
+
}
|
|
261
|
+
if (await provider.delete({ ...base, key, nativeVersion: created.nativeVersion }, context) !== "absent") {
|
|
262
|
+
throw new Error("repeated delete was not idempotent");
|
|
263
|
+
}
|
|
264
|
+
passed.push("exact-version-delete");
|
|
265
|
+
return passed;
|
|
266
|
+
}
|
|
267
|
+
function sha256Hex(value) {
|
|
268
|
+
return (0, import_crypto.createHash)("sha256").update(value).digest("hex");
|
|
269
|
+
}
|
|
270
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
271
|
+
0 && (module.exports = {
|
|
272
|
+
REPORTING_ROW_DEFAULT_KEY_TEMPLATE,
|
|
273
|
+
REPORTING_ROW_KEY_PLACEHOLDERS,
|
|
274
|
+
assertReportingRowKeyTemplateV1,
|
|
275
|
+
assertReportingRowPrefixV1,
|
|
276
|
+
createFilesystemReportingRowObjectProviderV1,
|
|
277
|
+
renderReportingRowObjectKeyV1,
|
|
278
|
+
reportingRowAccountKeyV1,
|
|
279
|
+
reportingRowRevisionKeyV1,
|
|
280
|
+
runReportingRowObjectProviderConformanceV1
|
|
281
|
+
});
|