@peac/transport-grpc 0.12.6
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/.turbo/turbo-build.log +25 -0
- package/.turbo/turbo-test.log +15 -0
- package/LICENSE +190 -0
- package/README.md +110 -0
- package/dist/a2a-carrier.d.ts +71 -0
- package/dist/a2a-carrier.d.ts.map +1 -0
- package/dist/index.cjs +324 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +137 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +297 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +304 -0
- package/dist/index.mjs.map +1 -0
- package/dist/metadata.d.ts +42 -0
- package/dist/metadata.d.ts.map +1 -0
- package/package.json +60 -0
- package/src/a2a-carrier.ts +158 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +313 -0
- package/src/metadata.ts +85 -0
- package/tests/a2a-carrier.test.ts +208 -0
- package/tests/status-parity.test.ts +361 -0
- package/tsconfig.json +11 -0
- package/tsup.config.ts +19 -0
- package/vitest.config.d.ts.map +1 -0
- package/vitest.config.js.map +1 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gRPC metadata keys, types, and helpers for PEAC transport.
|
|
3
|
+
*
|
|
4
|
+
* Extracted to a separate module to avoid circular imports between
|
|
5
|
+
* index.ts and a2a-carrier.ts.
|
|
6
|
+
*/
|
|
7
|
+
/** gRPC metadata shape for PEAC carrier operations */
|
|
8
|
+
export type GrpcMetadataLike = Record<string, string | string[] | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* gRPC metadata keys for PEAC transport.
|
|
11
|
+
*/
|
|
12
|
+
export declare const GrpcMetadataKeys: {
|
|
13
|
+
/** PEAC receipt in metadata */
|
|
14
|
+
readonly RECEIPT: "peac-receipt";
|
|
15
|
+
/** PEAC receipt type */
|
|
16
|
+
readonly RECEIPT_TYPE: "peac-receipt-type";
|
|
17
|
+
/** TAP signature */
|
|
18
|
+
readonly TAP_SIGNATURE: "peac-tap-signature";
|
|
19
|
+
/** TAP signature input */
|
|
20
|
+
readonly TAP_SIGNATURE_INPUT: "peac-tap-signature-input";
|
|
21
|
+
/** PEAC error code in trailer */
|
|
22
|
+
readonly ERROR_CODE: "peac-error-code";
|
|
23
|
+
/** Request ID for tracing */
|
|
24
|
+
readonly REQUEST_ID: "peac-request-id";
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Extract PEAC receipt from gRPC metadata.
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractReceiptFromMetadata(metadata: GrpcMetadataLike): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Extract receipt type from gRPC metadata.
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractReceiptTypeFromMetadata(metadata: GrpcMetadataLike): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Add PEAC receipt to gRPC metadata.
|
|
36
|
+
*
|
|
37
|
+
* @param metadata - gRPC metadata object to modify
|
|
38
|
+
* @param receiptJws - Compact JWS of the signed receipt
|
|
39
|
+
* @param receiptType - Receipt typ value (defaults to Wire 0.2 `interaction-record+jwt`)
|
|
40
|
+
*/
|
|
41
|
+
export declare function addReceiptToMetadata(metadata: Record<string, string | string[]>, receiptJws: string, receiptType?: string): void;
|
|
42
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,sDAAsD;AACtD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;AAM7E;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B,+BAA+B;;IAE/B,wBAAwB;;IAExB,oBAAoB;;IAEpB,0BAA0B;;IAE1B,iCAAiC;;IAEjC,6BAA6B;;CAErB,CAAC;AAMX;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CASpF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CASxF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC3C,UAAU,EAAE,MAAM,EAClB,WAAW,GAAE,MAAwB,GACpC,IAAI,CAGN"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peac/transport-grpc",
|
|
3
|
+
"version": "0.12.6",
|
|
4
|
+
"description": "PEAC gRPC transport layer with carrier adapter and HTTP StatusCode parity",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"peac",
|
|
21
|
+
"peacprotocol",
|
|
22
|
+
"interaction-records",
|
|
23
|
+
"signed-records",
|
|
24
|
+
"receipts",
|
|
25
|
+
"originary",
|
|
26
|
+
"transport-grpc",
|
|
27
|
+
"grpc",
|
|
28
|
+
"protobuf",
|
|
29
|
+
"rpc",
|
|
30
|
+
"carrier-adapter"
|
|
31
|
+
],
|
|
32
|
+
"author": "PEAC Protocol Contributors",
|
|
33
|
+
"license": "Apache-2.0",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@peac/kernel": "0.12.6",
|
|
36
|
+
"@peac/schema": "0.12.6"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"tsup": "^8.5.1",
|
|
40
|
+
"typescript": "^5.6.2",
|
|
41
|
+
"vitest": "^4.0.0"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/peacprotocol/peac/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/peacprotocol/peac#readme",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/peacprotocol/peac.git",
|
|
50
|
+
"directory": "packages/transport/grpc"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "pnpm run build:js && pnpm run build:types",
|
|
54
|
+
"build:js": "tsup",
|
|
55
|
+
"build:types": "rm -f dist/.tsbuildinfo && tsc && rm -f dist/.tsbuildinfo",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest",
|
|
58
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gRPC CarrierAdapter for A2A transport.
|
|
3
|
+
*
|
|
4
|
+
* Implements the PEAC CarrierAdapter interface for gRPC metadata,
|
|
5
|
+
* enabling receipt attach/extract via gRPC metadata keys. Pure TS
|
|
6
|
+
* with no @grpc/grpc-js dependency; consumers bring their own gRPC.
|
|
7
|
+
*
|
|
8
|
+
* Size default: 8 KiB. gRPC metadata rides in HTTP/2 headers where
|
|
9
|
+
* servers commonly enforce an 8 KiB limit. For larger receipts, use
|
|
10
|
+
* reference mode (receipt_url) or negotiate a higher limit with the
|
|
11
|
+
* gRPC server configuration.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createHash } from 'node:crypto';
|
|
15
|
+
|
|
16
|
+
import type {
|
|
17
|
+
CarrierAdapter,
|
|
18
|
+
PeacEvidenceCarrier,
|
|
19
|
+
CarrierMeta,
|
|
20
|
+
CarrierValidationResult,
|
|
21
|
+
ReceiptRef,
|
|
22
|
+
} from '@peac/kernel';
|
|
23
|
+
import { validateCarrierConstraints } from '@peac/schema';
|
|
24
|
+
|
|
25
|
+
import { GrpcMetadataKeys, extractReceiptFromMetadata, addReceiptToMetadata } from './metadata.js';
|
|
26
|
+
import type { GrpcMetadataLike } from './metadata.js';
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Constants
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Default maximum carrier size for gRPC metadata (8 KiB).
|
|
34
|
+
*
|
|
35
|
+
* gRPC metadata is carried in HTTP/2 headers. Official gRPC guidance
|
|
36
|
+
* warns that servers may limit request headers, with a common default
|
|
37
|
+
* of 8 KiB. This is a conservative interoperability-safe default.
|
|
38
|
+
* Consumers with known larger server limits can override via
|
|
39
|
+
* `createGrpcCarrierMeta({ max_size: ... })`.
|
|
40
|
+
*/
|
|
41
|
+
export const GRPC_MAX_CARRIER_SIZE = 8_192;
|
|
42
|
+
|
|
43
|
+
/** Binary metadata key suffix per gRPC convention */
|
|
44
|
+
const BINARY_SUFFIX = '-bin';
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Public API
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* CarrierAdapter for gRPC metadata transport.
|
|
52
|
+
*
|
|
53
|
+
* Reads and writes PEAC evidence carriers via `GrpcMetadataKeys.RECEIPT`
|
|
54
|
+
* and `GrpcMetadataKeys.RECEIPT_TYPE` metadata entries.
|
|
55
|
+
*
|
|
56
|
+
* `extract()` computes the real SHA-256 receipt_ref synchronously
|
|
57
|
+
* using Node's `crypto.createHash` (server-first package).
|
|
58
|
+
*/
|
|
59
|
+
export class A2AGrpcCarrierAdapter implements CarrierAdapter<GrpcMetadataLike, GrpcMetadataLike> {
|
|
60
|
+
/**
|
|
61
|
+
* Extract PEAC evidence carrier from gRPC metadata.
|
|
62
|
+
*
|
|
63
|
+
* Computes the real SHA-256 receipt_ref from the JWS bytes using
|
|
64
|
+
* Node's synchronous crypto.createHash (server-first package).
|
|
65
|
+
* Rejects binary metadata keys (gRPC `-bin` suffix convention).
|
|
66
|
+
*
|
|
67
|
+
* @returns Extracted carrier with computed receipt_ref, or null if absent
|
|
68
|
+
*/
|
|
69
|
+
extract(input: GrpcMetadataLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {
|
|
70
|
+
// Reject binary-encoded PEAC receipt metadata
|
|
71
|
+
const binaryReceiptKey = GrpcMetadataKeys.RECEIPT + BINARY_SUFFIX;
|
|
72
|
+
if (binaryReceiptKey in input) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const receiptJws = extractReceiptFromMetadata(input);
|
|
77
|
+
if (!receiptJws) return null;
|
|
78
|
+
|
|
79
|
+
const digest = createHash('sha256').update(receiptJws).digest('hex');
|
|
80
|
+
const receiptRef = `sha256:${digest}` as ReceiptRef;
|
|
81
|
+
|
|
82
|
+
const carrier: PeacEvidenceCarrier = {
|
|
83
|
+
receipt_ref: receiptRef,
|
|
84
|
+
receipt_jws: receiptJws,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
receipts: [carrier],
|
|
89
|
+
meta: createGrpcCarrierMeta(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
attach(
|
|
94
|
+
output: GrpcMetadataLike,
|
|
95
|
+
carriers: PeacEvidenceCarrier[],
|
|
96
|
+
meta?: CarrierMeta
|
|
97
|
+
): GrpcMetadataLike {
|
|
98
|
+
if (carriers.length === 0) return output;
|
|
99
|
+
|
|
100
|
+
const carrier = carriers[0];
|
|
101
|
+
const effectiveMeta = meta ?? createGrpcCarrierMeta();
|
|
102
|
+
const result = this.validateConstraints(carrier, effectiveMeta);
|
|
103
|
+
if (!result.valid) {
|
|
104
|
+
throw new Error(`Carrier constraint violation: ${result.violations.join('; ')}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (carrier.receipt_jws) {
|
|
108
|
+
addReceiptToMetadata(output as Record<string, string | string[]>, carrier.receipt_jws);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return output;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {
|
|
115
|
+
return validateCarrierConstraints(carrier, meta);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create default CarrierMeta for gRPC transport.
|
|
121
|
+
*
|
|
122
|
+
* Default max_size is 8 KiB (HTTP/2 header budget). Override for
|
|
123
|
+
* environments with known larger server limits.
|
|
124
|
+
*/
|
|
125
|
+
export function createGrpcCarrierMeta(overrides?: Partial<CarrierMeta>): CarrierMeta {
|
|
126
|
+
return {
|
|
127
|
+
transport: 'grpc',
|
|
128
|
+
format: 'embed',
|
|
129
|
+
max_size: GRPC_MAX_CARRIER_SIZE,
|
|
130
|
+
...overrides,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Validate that the package's own PEAC metadata key constants are ASCII-safe
|
|
136
|
+
* and do not use the reserved `grpc-` prefix.
|
|
137
|
+
*
|
|
138
|
+
* This is a repo-level invariant check, not an inbound metadata validator.
|
|
139
|
+
* It verifies that all keys defined in `GrpcMetadataKeys` use only
|
|
140
|
+
* lowercase ASCII letters, digits, hyphens, and underscores per
|
|
141
|
+
* gRPC metadata key requirements, and that none start with the
|
|
142
|
+
* reserved `grpc-` prefix.
|
|
143
|
+
*
|
|
144
|
+
* @returns Array of invalid keys (empty if all valid)
|
|
145
|
+
*/
|
|
146
|
+
export function validateOwnMetadataKeys(): string[] {
|
|
147
|
+
const ASCII_KEY_REGEX = /^[a-z0-9_-]+$/;
|
|
148
|
+
const RESERVED_PREFIX = 'grpc-';
|
|
149
|
+
const invalid: string[] = [];
|
|
150
|
+
for (const key of Object.values(GrpcMetadataKeys)) {
|
|
151
|
+
if (!ASCII_KEY_REGEX.test(key)) {
|
|
152
|
+
invalid.push(key);
|
|
153
|
+
} else if (key.startsWith(RESERVED_PREFIX)) {
|
|
154
|
+
invalid.push(key);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return invalid;
|
|
158
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,sBAAsB,EAAG,QAAiB,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,UAAU;IACrB,cAAc;;IAEd,8BAA8B;;IAE9B,oBAAoB;;IAEpB,wCAAwC;;IAExC,kDAAkD;;IAElD,iCAAiC;;IAEjC,4BAA4B;;IAE5B,8BAA8B;;IAE9B,yBAAyB;;IAEzB,6CAA6C;;IAE7C,mCAAmC;;IAEnC,yBAAyB;;IAEzB,gCAAgC;;IAEhC,qBAAqB;;IAErB,0BAA0B;;IAE1B,gBAAgB;;IAEhB,wBAAwB;;CAEhB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAuCnE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,cAAc,GAAG,MAAM,CAuCnE;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CA2B7D,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAEjE;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,uBAAuB;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAO/F;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B,+BAA+B;;IAE/B,wBAAwB;;IAExB,oBAAoB;;IAEpB,0BAA0B;;IAE1B,iCAAiC;;IAEjC,6BAA6B;;CAErB,CAAC;AAEX;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACtD,MAAM,GAAG,IAAI,CASf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC3C,UAAU,EAAE,MAAM,GACjB,IAAI,CAGN;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,uBAAuB;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,mCAAmC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,sBAAsB,CAM9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,sBAAsB,CAM5E;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAkBzD,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAE1D"}
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PEAC gRPC Transport Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides gRPC binding for PEAC receipts with StatusCode parity to HTTP.
|
|
5
|
+
*
|
|
6
|
+
* Status code mapping follows these semantics:
|
|
7
|
+
* - INVALID_ARGUMENT (3): Malformed request (HTTP 400)
|
|
8
|
+
* - UNAUTHENTICATED (16): Authentication required (HTTP 401)
|
|
9
|
+
* - FAILED_PRECONDITION (9): Payment required (HTTP 402)
|
|
10
|
+
* - PERMISSION_DENIED (7): Not authorized (HTTP 403)
|
|
11
|
+
* - ABORTED (10): Conflict/replay detected (HTTP 409)
|
|
12
|
+
* - INTERNAL (13): Server error (HTTP 500)
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export const GRPC_TRANSPORT_VERSION = '0.12.6' as const;
|
|
18
|
+
|
|
19
|
+
// Metadata keys, types, and helpers (shared with a2a-carrier.ts)
|
|
20
|
+
export {
|
|
21
|
+
GrpcMetadataKeys,
|
|
22
|
+
extractReceiptFromMetadata,
|
|
23
|
+
extractReceiptTypeFromMetadata,
|
|
24
|
+
addReceiptToMetadata,
|
|
25
|
+
} from './metadata.js';
|
|
26
|
+
export type { GrpcMetadataLike } from './metadata.js';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* gRPC status codes.
|
|
30
|
+
* @see https://grpc.io/docs/guides/status-codes/
|
|
31
|
+
*/
|
|
32
|
+
export const GrpcStatus = {
|
|
33
|
+
/** Success */
|
|
34
|
+
OK: 0,
|
|
35
|
+
/** Operation was cancelled */
|
|
36
|
+
CANCELLED: 1,
|
|
37
|
+
/** Unknown error */
|
|
38
|
+
UNKNOWN: 2,
|
|
39
|
+
/** Client specified invalid argument */
|
|
40
|
+
INVALID_ARGUMENT: 3,
|
|
41
|
+
/** Deadline expired before operation completed */
|
|
42
|
+
DEADLINE_EXCEEDED: 4,
|
|
43
|
+
/** Requested entity not found */
|
|
44
|
+
NOT_FOUND: 5,
|
|
45
|
+
/** Entity already exists */
|
|
46
|
+
ALREADY_EXISTS: 6,
|
|
47
|
+
/** Caller lacks permission */
|
|
48
|
+
PERMISSION_DENIED: 7,
|
|
49
|
+
/** Resource exhausted */
|
|
50
|
+
RESOURCE_EXHAUSTED: 8,
|
|
51
|
+
/** Operation rejected due to precondition */
|
|
52
|
+
FAILED_PRECONDITION: 9,
|
|
53
|
+
/** Operation aborted (conflict) */
|
|
54
|
+
ABORTED: 10,
|
|
55
|
+
/** Value out of range */
|
|
56
|
+
OUT_OF_RANGE: 11,
|
|
57
|
+
/** Operation not implemented */
|
|
58
|
+
UNIMPLEMENTED: 12,
|
|
59
|
+
/** Internal error */
|
|
60
|
+
INTERNAL: 13,
|
|
61
|
+
/** Service unavailable */
|
|
62
|
+
UNAVAILABLE: 14,
|
|
63
|
+
/** Data loss */
|
|
64
|
+
DATA_LOSS: 15,
|
|
65
|
+
/** Not authenticated */
|
|
66
|
+
UNAUTHENTICATED: 16,
|
|
67
|
+
} as const;
|
|
68
|
+
|
|
69
|
+
export type GrpcStatusCode = (typeof GrpcStatus)[keyof typeof GrpcStatus];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Map HTTP status code to gRPC status code.
|
|
73
|
+
*
|
|
74
|
+
* Mapping semantics:
|
|
75
|
+
* - 400 Bad Request -> INVALID_ARGUMENT (malformed)
|
|
76
|
+
* - 401 Unauthorized -> UNAUTHENTICATED (auth required)
|
|
77
|
+
* - 402 Payment Required -> FAILED_PRECONDITION (payment needed)
|
|
78
|
+
* - 403 Forbidden -> PERMISSION_DENIED (not authorized)
|
|
79
|
+
* - 409 Conflict -> ABORTED (replay detected)
|
|
80
|
+
* - 500 Internal Server Error -> INTERNAL
|
|
81
|
+
* - Other 4xx -> INVALID_ARGUMENT
|
|
82
|
+
* - Other 5xx -> INTERNAL
|
|
83
|
+
*/
|
|
84
|
+
export function httpStatusToGrpc(httpStatus: number): GrpcStatusCode {
|
|
85
|
+
switch (httpStatus) {
|
|
86
|
+
case 200:
|
|
87
|
+
case 201:
|
|
88
|
+
case 204:
|
|
89
|
+
return GrpcStatus.OK;
|
|
90
|
+
case 400:
|
|
91
|
+
return GrpcStatus.INVALID_ARGUMENT;
|
|
92
|
+
case 401:
|
|
93
|
+
return GrpcStatus.UNAUTHENTICATED;
|
|
94
|
+
case 402:
|
|
95
|
+
return GrpcStatus.FAILED_PRECONDITION;
|
|
96
|
+
case 403:
|
|
97
|
+
return GrpcStatus.PERMISSION_DENIED;
|
|
98
|
+
case 404:
|
|
99
|
+
return GrpcStatus.NOT_FOUND;
|
|
100
|
+
case 409:
|
|
101
|
+
return GrpcStatus.ABORTED;
|
|
102
|
+
case 429:
|
|
103
|
+
return GrpcStatus.RESOURCE_EXHAUSTED;
|
|
104
|
+
case 499:
|
|
105
|
+
return GrpcStatus.CANCELLED;
|
|
106
|
+
case 500:
|
|
107
|
+
return GrpcStatus.INTERNAL;
|
|
108
|
+
case 501:
|
|
109
|
+
return GrpcStatus.UNIMPLEMENTED;
|
|
110
|
+
case 503:
|
|
111
|
+
return GrpcStatus.UNAVAILABLE;
|
|
112
|
+
case 504:
|
|
113
|
+
return GrpcStatus.DEADLINE_EXCEEDED;
|
|
114
|
+
default:
|
|
115
|
+
if (httpStatus >= 400 && httpStatus < 500) {
|
|
116
|
+
return GrpcStatus.INVALID_ARGUMENT;
|
|
117
|
+
}
|
|
118
|
+
if (httpStatus >= 500) {
|
|
119
|
+
return GrpcStatus.INTERNAL;
|
|
120
|
+
}
|
|
121
|
+
return GrpcStatus.OK;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Map gRPC status code to HTTP status code.
|
|
127
|
+
*
|
|
128
|
+
* Inverse of httpStatusToGrpc for response translation.
|
|
129
|
+
*/
|
|
130
|
+
export function grpcStatusToHttp(grpcStatus: GrpcStatusCode): number {
|
|
131
|
+
switch (grpcStatus) {
|
|
132
|
+
case GrpcStatus.OK:
|
|
133
|
+
return 200;
|
|
134
|
+
case GrpcStatus.CANCELLED:
|
|
135
|
+
return 499;
|
|
136
|
+
case GrpcStatus.UNKNOWN:
|
|
137
|
+
return 500;
|
|
138
|
+
case GrpcStatus.INVALID_ARGUMENT:
|
|
139
|
+
return 400;
|
|
140
|
+
case GrpcStatus.DEADLINE_EXCEEDED:
|
|
141
|
+
return 504;
|
|
142
|
+
case GrpcStatus.NOT_FOUND:
|
|
143
|
+
return 404;
|
|
144
|
+
case GrpcStatus.ALREADY_EXISTS:
|
|
145
|
+
return 409;
|
|
146
|
+
case GrpcStatus.PERMISSION_DENIED:
|
|
147
|
+
return 403;
|
|
148
|
+
case GrpcStatus.RESOURCE_EXHAUSTED:
|
|
149
|
+
return 429;
|
|
150
|
+
case GrpcStatus.FAILED_PRECONDITION:
|
|
151
|
+
return 402;
|
|
152
|
+
case GrpcStatus.ABORTED:
|
|
153
|
+
return 409;
|
|
154
|
+
case GrpcStatus.OUT_OF_RANGE:
|
|
155
|
+
return 400;
|
|
156
|
+
case GrpcStatus.UNIMPLEMENTED:
|
|
157
|
+
return 501;
|
|
158
|
+
case GrpcStatus.INTERNAL:
|
|
159
|
+
return 500;
|
|
160
|
+
case GrpcStatus.UNAVAILABLE:
|
|
161
|
+
return 503;
|
|
162
|
+
case GrpcStatus.DATA_LOSS:
|
|
163
|
+
return 500;
|
|
164
|
+
case GrpcStatus.UNAUTHENTICATED:
|
|
165
|
+
return 401;
|
|
166
|
+
default:
|
|
167
|
+
return 500;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* PEAC error code to gRPC status mapping.
|
|
173
|
+
*
|
|
174
|
+
* Maps canonical PEAC error codes to appropriate gRPC status codes.
|
|
175
|
+
*/
|
|
176
|
+
export const PEAC_ERROR_TO_GRPC: Record<string, GrpcStatusCode> = {
|
|
177
|
+
// 402 Payment Required -> FAILED_PRECONDITION
|
|
178
|
+
E_RECEIPT_MISSING: GrpcStatus.FAILED_PRECONDITION,
|
|
179
|
+
E_RECEIPT_INVALID: GrpcStatus.FAILED_PRECONDITION,
|
|
180
|
+
E_RECEIPT_EXPIRED: GrpcStatus.FAILED_PRECONDITION,
|
|
181
|
+
|
|
182
|
+
// 401 Unauthenticated -> UNAUTHENTICATED
|
|
183
|
+
E_TAP_SIGNATURE_MISSING: GrpcStatus.UNAUTHENTICATED,
|
|
184
|
+
E_TAP_SIGNATURE_INVALID: GrpcStatus.UNAUTHENTICATED,
|
|
185
|
+
E_TAP_TIME_INVALID: GrpcStatus.UNAUTHENTICATED,
|
|
186
|
+
E_TAP_KEY_NOT_FOUND: GrpcStatus.UNAUTHENTICATED,
|
|
187
|
+
E_TAP_REPLAY_PROTECTION_REQUIRED: GrpcStatus.UNAUTHENTICATED,
|
|
188
|
+
|
|
189
|
+
// 400 Bad Request -> INVALID_ARGUMENT
|
|
190
|
+
E_TAP_WINDOW_TOO_LARGE: GrpcStatus.INVALID_ARGUMENT,
|
|
191
|
+
E_TAP_TAG_UNKNOWN: GrpcStatus.INVALID_ARGUMENT,
|
|
192
|
+
E_TAP_ALGORITHM_INVALID: GrpcStatus.INVALID_ARGUMENT,
|
|
193
|
+
|
|
194
|
+
// 403 Forbidden -> PERMISSION_DENIED
|
|
195
|
+
E_ISSUER_NOT_ALLOWED: GrpcStatus.PERMISSION_DENIED,
|
|
196
|
+
|
|
197
|
+
// 409 Conflict -> ABORTED
|
|
198
|
+
E_TAP_NONCE_REPLAY: GrpcStatus.ABORTED,
|
|
199
|
+
|
|
200
|
+
// 500 Internal -> INTERNAL
|
|
201
|
+
E_CONFIG_ISSUER_ALLOWLIST_REQUIRED: GrpcStatus.INTERNAL,
|
|
202
|
+
E_INTERNAL_ERROR: GrpcStatus.INTERNAL,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get gRPC status for a PEAC error code.
|
|
207
|
+
*/
|
|
208
|
+
export function peacErrorToGrpc(errorCode: string): GrpcStatusCode {
|
|
209
|
+
return PEAC_ERROR_TO_GRPC[errorCode] ?? GrpcStatus.INTERNAL;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* gRPC error with status code.
|
|
214
|
+
*/
|
|
215
|
+
export interface GrpcError {
|
|
216
|
+
/** gRPC status code */
|
|
217
|
+
code: GrpcStatusCode;
|
|
218
|
+
/** Error message */
|
|
219
|
+
message: string;
|
|
220
|
+
/** PEAC error code (if applicable) */
|
|
221
|
+
peacCode?: string;
|
|
222
|
+
/** Additional error details */
|
|
223
|
+
details?: unknown;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Create a gRPC error from a PEAC error code.
|
|
228
|
+
*/
|
|
229
|
+
export function createGrpcError(peacCode: string, message: string, details?: unknown): GrpcError {
|
|
230
|
+
return {
|
|
231
|
+
code: peacErrorToGrpc(peacCode),
|
|
232
|
+
message,
|
|
233
|
+
peacCode,
|
|
234
|
+
details,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* gRPC verification result.
|
|
240
|
+
*/
|
|
241
|
+
export interface GrpcVerificationResult {
|
|
242
|
+
/** Whether verification succeeded */
|
|
243
|
+
ok: boolean;
|
|
244
|
+
/** gRPC status code */
|
|
245
|
+
status: GrpcStatusCode;
|
|
246
|
+
/** Error if verification failed */
|
|
247
|
+
error?: GrpcError;
|
|
248
|
+
/** Receipt ID if verification succeeded */
|
|
249
|
+
receiptId?: string;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Create a successful verification result.
|
|
254
|
+
*/
|
|
255
|
+
export function createSuccessResult(receiptId?: string): GrpcVerificationResult {
|
|
256
|
+
return {
|
|
257
|
+
ok: true,
|
|
258
|
+
status: GrpcStatus.OK,
|
|
259
|
+
receiptId,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Create a failed verification result.
|
|
265
|
+
*/
|
|
266
|
+
export function createFailureResult(error: GrpcError): GrpcVerificationResult {
|
|
267
|
+
return {
|
|
268
|
+
ok: false,
|
|
269
|
+
status: error.code,
|
|
270
|
+
error,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Status code name mapping for debugging.
|
|
276
|
+
*/
|
|
277
|
+
export const GrpcStatusName: Record<GrpcStatusCode, string> = {
|
|
278
|
+
[GrpcStatus.OK]: 'OK',
|
|
279
|
+
[GrpcStatus.CANCELLED]: 'CANCELLED',
|
|
280
|
+
[GrpcStatus.UNKNOWN]: 'UNKNOWN',
|
|
281
|
+
[GrpcStatus.INVALID_ARGUMENT]: 'INVALID_ARGUMENT',
|
|
282
|
+
[GrpcStatus.DEADLINE_EXCEEDED]: 'DEADLINE_EXCEEDED',
|
|
283
|
+
[GrpcStatus.NOT_FOUND]: 'NOT_FOUND',
|
|
284
|
+
[GrpcStatus.ALREADY_EXISTS]: 'ALREADY_EXISTS',
|
|
285
|
+
[GrpcStatus.PERMISSION_DENIED]: 'PERMISSION_DENIED',
|
|
286
|
+
[GrpcStatus.RESOURCE_EXHAUSTED]: 'RESOURCE_EXHAUSTED',
|
|
287
|
+
[GrpcStatus.FAILED_PRECONDITION]: 'FAILED_PRECONDITION',
|
|
288
|
+
[GrpcStatus.ABORTED]: 'ABORTED',
|
|
289
|
+
[GrpcStatus.OUT_OF_RANGE]: 'OUT_OF_RANGE',
|
|
290
|
+
[GrpcStatus.UNIMPLEMENTED]: 'UNIMPLEMENTED',
|
|
291
|
+
[GrpcStatus.INTERNAL]: 'INTERNAL',
|
|
292
|
+
[GrpcStatus.UNAVAILABLE]: 'UNAVAILABLE',
|
|
293
|
+
[GrpcStatus.DATA_LOSS]: 'DATA_LOSS',
|
|
294
|
+
[GrpcStatus.UNAUTHENTICATED]: 'UNAUTHENTICATED',
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get human-readable name for a gRPC status code.
|
|
299
|
+
*/
|
|
300
|
+
export function getStatusName(code: GrpcStatusCode): string {
|
|
301
|
+
return GrpcStatusName[code] ?? 'UNKNOWN';
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ---------------------------------------------------------------------------
|
|
305
|
+
// Carrier adapter re-exports
|
|
306
|
+
// ---------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
export {
|
|
309
|
+
A2AGrpcCarrierAdapter,
|
|
310
|
+
createGrpcCarrierMeta,
|
|
311
|
+
validateOwnMetadataKeys,
|
|
312
|
+
GRPC_MAX_CARRIER_SIZE,
|
|
313
|
+
} from './a2a-carrier.js';
|
package/src/metadata.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gRPC metadata keys, types, and helpers for PEAC transport.
|
|
3
|
+
*
|
|
4
|
+
* Extracted to a separate module to avoid circular imports between
|
|
5
|
+
* index.ts and a2a-carrier.ts.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { WIRE_02_JWS_TYP } from '@peac/kernel';
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Types
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
/** gRPC metadata shape for PEAC carrier operations */
|
|
15
|
+
export type GrpcMetadataLike = Record<string, string | string[] | undefined>;
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Constants
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* gRPC metadata keys for PEAC transport.
|
|
23
|
+
*/
|
|
24
|
+
export const GrpcMetadataKeys = {
|
|
25
|
+
/** PEAC receipt in metadata */
|
|
26
|
+
RECEIPT: 'peac-receipt',
|
|
27
|
+
/** PEAC receipt type */
|
|
28
|
+
RECEIPT_TYPE: 'peac-receipt-type',
|
|
29
|
+
/** TAP signature */
|
|
30
|
+
TAP_SIGNATURE: 'peac-tap-signature',
|
|
31
|
+
/** TAP signature input */
|
|
32
|
+
TAP_SIGNATURE_INPUT: 'peac-tap-signature-input',
|
|
33
|
+
/** PEAC error code in trailer */
|
|
34
|
+
ERROR_CODE: 'peac-error-code',
|
|
35
|
+
/** Request ID for tracing */
|
|
36
|
+
REQUEST_ID: 'peac-request-id',
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helpers
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Extract PEAC receipt from gRPC metadata.
|
|
45
|
+
*/
|
|
46
|
+
export function extractReceiptFromMetadata(metadata: GrpcMetadataLike): string | null {
|
|
47
|
+
const receipt = metadata[GrpcMetadataKeys.RECEIPT];
|
|
48
|
+
if (typeof receipt === 'string') {
|
|
49
|
+
return receipt;
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(receipt) && receipt.length > 0) {
|
|
52
|
+
return receipt[0];
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Extract receipt type from gRPC metadata.
|
|
59
|
+
*/
|
|
60
|
+
export function extractReceiptTypeFromMetadata(metadata: GrpcMetadataLike): string | null {
|
|
61
|
+
const typ = metadata[GrpcMetadataKeys.RECEIPT_TYPE];
|
|
62
|
+
if (typeof typ === 'string') {
|
|
63
|
+
return typ;
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(typ) && typ.length > 0) {
|
|
66
|
+
return typ[0];
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Add PEAC receipt to gRPC metadata.
|
|
73
|
+
*
|
|
74
|
+
* @param metadata - gRPC metadata object to modify
|
|
75
|
+
* @param receiptJws - Compact JWS of the signed receipt
|
|
76
|
+
* @param receiptType - Receipt typ value (defaults to Wire 0.2 `interaction-record+jwt`)
|
|
77
|
+
*/
|
|
78
|
+
export function addReceiptToMetadata(
|
|
79
|
+
metadata: Record<string, string | string[]>,
|
|
80
|
+
receiptJws: string,
|
|
81
|
+
receiptType: string = WIRE_02_JWS_TYP
|
|
82
|
+
): void {
|
|
83
|
+
metadata[GrpcMetadataKeys.RECEIPT] = receiptJws;
|
|
84
|
+
metadata[GrpcMetadataKeys.RECEIPT_TYPE] = receiptType;
|
|
85
|
+
}
|