@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
package/dist/index.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PEAC gRPC Transport Layer
|
|
4
|
+
*
|
|
5
|
+
* Provides gRPC binding for PEAC receipts with StatusCode parity to HTTP.
|
|
6
|
+
*
|
|
7
|
+
* Status code mapping follows these semantics:
|
|
8
|
+
* - INVALID_ARGUMENT (3): Malformed request (HTTP 400)
|
|
9
|
+
* - UNAUTHENTICATED (16): Authentication required (HTTP 401)
|
|
10
|
+
* - FAILED_PRECONDITION (9): Payment required (HTTP 402)
|
|
11
|
+
* - PERMISSION_DENIED (7): Not authorized (HTTP 403)
|
|
12
|
+
* - ABORTED (10): Conflict/replay detected (HTTP 409)
|
|
13
|
+
* - INTERNAL (13): Server error (HTTP 500)
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.GrpcStatusName = exports.GrpcMetadataKeys = exports.PEAC_ERROR_TO_GRPC = exports.GrpcStatus = exports.GRPC_TRANSPORT_VERSION = void 0;
|
|
19
|
+
exports.httpStatusToGrpc = httpStatusToGrpc;
|
|
20
|
+
exports.grpcStatusToHttp = grpcStatusToHttp;
|
|
21
|
+
exports.peacErrorToGrpc = peacErrorToGrpc;
|
|
22
|
+
exports.createGrpcError = createGrpcError;
|
|
23
|
+
exports.extractReceiptFromMetadata = extractReceiptFromMetadata;
|
|
24
|
+
exports.addReceiptToMetadata = addReceiptToMetadata;
|
|
25
|
+
exports.createSuccessResult = createSuccessResult;
|
|
26
|
+
exports.createFailureResult = createFailureResult;
|
|
27
|
+
exports.getStatusName = getStatusName;
|
|
28
|
+
exports.GRPC_TRANSPORT_VERSION = '0.9.20';
|
|
29
|
+
/**
|
|
30
|
+
* gRPC status codes.
|
|
31
|
+
* @see https://grpc.io/docs/guides/status-codes/
|
|
32
|
+
*/
|
|
33
|
+
exports.GrpcStatus = {
|
|
34
|
+
/** Success */
|
|
35
|
+
OK: 0,
|
|
36
|
+
/** Operation was cancelled */
|
|
37
|
+
CANCELLED: 1,
|
|
38
|
+
/** Unknown error */
|
|
39
|
+
UNKNOWN: 2,
|
|
40
|
+
/** Client specified invalid argument */
|
|
41
|
+
INVALID_ARGUMENT: 3,
|
|
42
|
+
/** Deadline expired before operation completed */
|
|
43
|
+
DEADLINE_EXCEEDED: 4,
|
|
44
|
+
/** Requested entity not found */
|
|
45
|
+
NOT_FOUND: 5,
|
|
46
|
+
/** Entity already exists */
|
|
47
|
+
ALREADY_EXISTS: 6,
|
|
48
|
+
/** Caller lacks permission */
|
|
49
|
+
PERMISSION_DENIED: 7,
|
|
50
|
+
/** Resource exhausted */
|
|
51
|
+
RESOURCE_EXHAUSTED: 8,
|
|
52
|
+
/** Operation rejected due to precondition */
|
|
53
|
+
FAILED_PRECONDITION: 9,
|
|
54
|
+
/** Operation aborted (conflict) */
|
|
55
|
+
ABORTED: 10,
|
|
56
|
+
/** Value out of range */
|
|
57
|
+
OUT_OF_RANGE: 11,
|
|
58
|
+
/** Operation not implemented */
|
|
59
|
+
UNIMPLEMENTED: 12,
|
|
60
|
+
/** Internal error */
|
|
61
|
+
INTERNAL: 13,
|
|
62
|
+
/** Service unavailable */
|
|
63
|
+
UNAVAILABLE: 14,
|
|
64
|
+
/** Data loss */
|
|
65
|
+
DATA_LOSS: 15,
|
|
66
|
+
/** Not authenticated */
|
|
67
|
+
UNAUTHENTICATED: 16,
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Map HTTP status code to gRPC status code.
|
|
71
|
+
*
|
|
72
|
+
* Mapping semantics:
|
|
73
|
+
* - 400 Bad Request -> INVALID_ARGUMENT (malformed)
|
|
74
|
+
* - 401 Unauthorized -> UNAUTHENTICATED (auth required)
|
|
75
|
+
* - 402 Payment Required -> FAILED_PRECONDITION (payment needed)
|
|
76
|
+
* - 403 Forbidden -> PERMISSION_DENIED (not authorized)
|
|
77
|
+
* - 409 Conflict -> ABORTED (replay detected)
|
|
78
|
+
* - 500 Internal Server Error -> INTERNAL
|
|
79
|
+
* - Other 4xx -> INVALID_ARGUMENT
|
|
80
|
+
* - Other 5xx -> INTERNAL
|
|
81
|
+
*/
|
|
82
|
+
function httpStatusToGrpc(httpStatus) {
|
|
83
|
+
switch (httpStatus) {
|
|
84
|
+
case 200:
|
|
85
|
+
case 201:
|
|
86
|
+
case 204:
|
|
87
|
+
return exports.GrpcStatus.OK;
|
|
88
|
+
case 400:
|
|
89
|
+
return exports.GrpcStatus.INVALID_ARGUMENT;
|
|
90
|
+
case 401:
|
|
91
|
+
return exports.GrpcStatus.UNAUTHENTICATED;
|
|
92
|
+
case 402:
|
|
93
|
+
return exports.GrpcStatus.FAILED_PRECONDITION;
|
|
94
|
+
case 403:
|
|
95
|
+
return exports.GrpcStatus.PERMISSION_DENIED;
|
|
96
|
+
case 404:
|
|
97
|
+
return exports.GrpcStatus.NOT_FOUND;
|
|
98
|
+
case 409:
|
|
99
|
+
return exports.GrpcStatus.ABORTED;
|
|
100
|
+
case 429:
|
|
101
|
+
return exports.GrpcStatus.RESOURCE_EXHAUSTED;
|
|
102
|
+
case 499:
|
|
103
|
+
return exports.GrpcStatus.CANCELLED;
|
|
104
|
+
case 500:
|
|
105
|
+
return exports.GrpcStatus.INTERNAL;
|
|
106
|
+
case 501:
|
|
107
|
+
return exports.GrpcStatus.UNIMPLEMENTED;
|
|
108
|
+
case 503:
|
|
109
|
+
return exports.GrpcStatus.UNAVAILABLE;
|
|
110
|
+
case 504:
|
|
111
|
+
return exports.GrpcStatus.DEADLINE_EXCEEDED;
|
|
112
|
+
default:
|
|
113
|
+
if (httpStatus >= 400 && httpStatus < 500) {
|
|
114
|
+
return exports.GrpcStatus.INVALID_ARGUMENT;
|
|
115
|
+
}
|
|
116
|
+
if (httpStatus >= 500) {
|
|
117
|
+
return exports.GrpcStatus.INTERNAL;
|
|
118
|
+
}
|
|
119
|
+
return exports.GrpcStatus.OK;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Map gRPC status code to HTTP status code.
|
|
124
|
+
*
|
|
125
|
+
* Inverse of httpStatusToGrpc for response translation.
|
|
126
|
+
*/
|
|
127
|
+
function grpcStatusToHttp(grpcStatus) {
|
|
128
|
+
switch (grpcStatus) {
|
|
129
|
+
case exports.GrpcStatus.OK:
|
|
130
|
+
return 200;
|
|
131
|
+
case exports.GrpcStatus.CANCELLED:
|
|
132
|
+
return 499;
|
|
133
|
+
case exports.GrpcStatus.UNKNOWN:
|
|
134
|
+
return 500;
|
|
135
|
+
case exports.GrpcStatus.INVALID_ARGUMENT:
|
|
136
|
+
return 400;
|
|
137
|
+
case exports.GrpcStatus.DEADLINE_EXCEEDED:
|
|
138
|
+
return 504;
|
|
139
|
+
case exports.GrpcStatus.NOT_FOUND:
|
|
140
|
+
return 404;
|
|
141
|
+
case exports.GrpcStatus.ALREADY_EXISTS:
|
|
142
|
+
return 409;
|
|
143
|
+
case exports.GrpcStatus.PERMISSION_DENIED:
|
|
144
|
+
return 403;
|
|
145
|
+
case exports.GrpcStatus.RESOURCE_EXHAUSTED:
|
|
146
|
+
return 429;
|
|
147
|
+
case exports.GrpcStatus.FAILED_PRECONDITION:
|
|
148
|
+
return 402;
|
|
149
|
+
case exports.GrpcStatus.ABORTED:
|
|
150
|
+
return 409;
|
|
151
|
+
case exports.GrpcStatus.OUT_OF_RANGE:
|
|
152
|
+
return 400;
|
|
153
|
+
case exports.GrpcStatus.UNIMPLEMENTED:
|
|
154
|
+
return 501;
|
|
155
|
+
case exports.GrpcStatus.INTERNAL:
|
|
156
|
+
return 500;
|
|
157
|
+
case exports.GrpcStatus.UNAVAILABLE:
|
|
158
|
+
return 503;
|
|
159
|
+
case exports.GrpcStatus.DATA_LOSS:
|
|
160
|
+
return 500;
|
|
161
|
+
case exports.GrpcStatus.UNAUTHENTICATED:
|
|
162
|
+
return 401;
|
|
163
|
+
default:
|
|
164
|
+
return 500;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* PEAC error code to gRPC status mapping.
|
|
169
|
+
*
|
|
170
|
+
* Maps canonical PEAC error codes to appropriate gRPC status codes.
|
|
171
|
+
*/
|
|
172
|
+
exports.PEAC_ERROR_TO_GRPC = {
|
|
173
|
+
// 402 Payment Required -> FAILED_PRECONDITION
|
|
174
|
+
E_RECEIPT_MISSING: exports.GrpcStatus.FAILED_PRECONDITION,
|
|
175
|
+
E_RECEIPT_INVALID: exports.GrpcStatus.FAILED_PRECONDITION,
|
|
176
|
+
E_RECEIPT_EXPIRED: exports.GrpcStatus.FAILED_PRECONDITION,
|
|
177
|
+
// 401 Unauthenticated -> UNAUTHENTICATED
|
|
178
|
+
E_TAP_SIGNATURE_MISSING: exports.GrpcStatus.UNAUTHENTICATED,
|
|
179
|
+
E_TAP_SIGNATURE_INVALID: exports.GrpcStatus.UNAUTHENTICATED,
|
|
180
|
+
E_TAP_TIME_INVALID: exports.GrpcStatus.UNAUTHENTICATED,
|
|
181
|
+
E_TAP_KEY_NOT_FOUND: exports.GrpcStatus.UNAUTHENTICATED,
|
|
182
|
+
E_TAP_REPLAY_PROTECTION_REQUIRED: exports.GrpcStatus.UNAUTHENTICATED,
|
|
183
|
+
// 400 Bad Request -> INVALID_ARGUMENT
|
|
184
|
+
E_TAP_WINDOW_TOO_LARGE: exports.GrpcStatus.INVALID_ARGUMENT,
|
|
185
|
+
E_TAP_TAG_UNKNOWN: exports.GrpcStatus.INVALID_ARGUMENT,
|
|
186
|
+
E_TAP_ALGORITHM_INVALID: exports.GrpcStatus.INVALID_ARGUMENT,
|
|
187
|
+
// 403 Forbidden -> PERMISSION_DENIED
|
|
188
|
+
E_ISSUER_NOT_ALLOWED: exports.GrpcStatus.PERMISSION_DENIED,
|
|
189
|
+
// 409 Conflict -> ABORTED
|
|
190
|
+
E_TAP_NONCE_REPLAY: exports.GrpcStatus.ABORTED,
|
|
191
|
+
// 500 Internal -> INTERNAL
|
|
192
|
+
E_CONFIG_ISSUER_ALLOWLIST_REQUIRED: exports.GrpcStatus.INTERNAL,
|
|
193
|
+
E_INTERNAL_ERROR: exports.GrpcStatus.INTERNAL,
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Get gRPC status for a PEAC error code.
|
|
197
|
+
*/
|
|
198
|
+
function peacErrorToGrpc(errorCode) {
|
|
199
|
+
return exports.PEAC_ERROR_TO_GRPC[errorCode] ?? exports.GrpcStatus.INTERNAL;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Create a gRPC error from a PEAC error code.
|
|
203
|
+
*/
|
|
204
|
+
function createGrpcError(peacCode, message, details) {
|
|
205
|
+
return {
|
|
206
|
+
code: peacErrorToGrpc(peacCode),
|
|
207
|
+
message,
|
|
208
|
+
peacCode,
|
|
209
|
+
details,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* gRPC metadata keys for PEAC transport.
|
|
214
|
+
*/
|
|
215
|
+
exports.GrpcMetadataKeys = {
|
|
216
|
+
/** PEAC receipt in metadata */
|
|
217
|
+
RECEIPT: 'peac-receipt',
|
|
218
|
+
/** PEAC receipt type */
|
|
219
|
+
RECEIPT_TYPE: 'peac-receipt-type',
|
|
220
|
+
/** TAP signature */
|
|
221
|
+
TAP_SIGNATURE: 'peac-tap-signature',
|
|
222
|
+
/** TAP signature input */
|
|
223
|
+
TAP_SIGNATURE_INPUT: 'peac-tap-signature-input',
|
|
224
|
+
/** PEAC error code in trailer */
|
|
225
|
+
ERROR_CODE: 'peac-error-code',
|
|
226
|
+
/** Request ID for tracing */
|
|
227
|
+
REQUEST_ID: 'peac-request-id',
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Extract PEAC receipt from gRPC metadata.
|
|
231
|
+
*/
|
|
232
|
+
function extractReceiptFromMetadata(metadata) {
|
|
233
|
+
const receipt = metadata[exports.GrpcMetadataKeys.RECEIPT];
|
|
234
|
+
if (typeof receipt === 'string') {
|
|
235
|
+
return receipt;
|
|
236
|
+
}
|
|
237
|
+
if (Array.isArray(receipt) && receipt.length > 0) {
|
|
238
|
+
return receipt[0];
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Add PEAC receipt to gRPC metadata.
|
|
244
|
+
*/
|
|
245
|
+
function addReceiptToMetadata(metadata, receiptJws) {
|
|
246
|
+
metadata[exports.GrpcMetadataKeys.RECEIPT] = receiptJws;
|
|
247
|
+
metadata[exports.GrpcMetadataKeys.RECEIPT_TYPE] = 'peac-receipt/0.1';
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Create a successful verification result.
|
|
251
|
+
*/
|
|
252
|
+
function createSuccessResult(receiptId) {
|
|
253
|
+
return {
|
|
254
|
+
ok: true,
|
|
255
|
+
status: exports.GrpcStatus.OK,
|
|
256
|
+
receiptId,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Create a failed verification result.
|
|
261
|
+
*/
|
|
262
|
+
function createFailureResult(error) {
|
|
263
|
+
return {
|
|
264
|
+
ok: false,
|
|
265
|
+
status: error.code,
|
|
266
|
+
error,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Status code name mapping for debugging.
|
|
271
|
+
*/
|
|
272
|
+
exports.GrpcStatusName = {
|
|
273
|
+
[exports.GrpcStatus.OK]: 'OK',
|
|
274
|
+
[exports.GrpcStatus.CANCELLED]: 'CANCELLED',
|
|
275
|
+
[exports.GrpcStatus.UNKNOWN]: 'UNKNOWN',
|
|
276
|
+
[exports.GrpcStatus.INVALID_ARGUMENT]: 'INVALID_ARGUMENT',
|
|
277
|
+
[exports.GrpcStatus.DEADLINE_EXCEEDED]: 'DEADLINE_EXCEEDED',
|
|
278
|
+
[exports.GrpcStatus.NOT_FOUND]: 'NOT_FOUND',
|
|
279
|
+
[exports.GrpcStatus.ALREADY_EXISTS]: 'ALREADY_EXISTS',
|
|
280
|
+
[exports.GrpcStatus.PERMISSION_DENIED]: 'PERMISSION_DENIED',
|
|
281
|
+
[exports.GrpcStatus.RESOURCE_EXHAUSTED]: 'RESOURCE_EXHAUSTED',
|
|
282
|
+
[exports.GrpcStatus.FAILED_PRECONDITION]: 'FAILED_PRECONDITION',
|
|
283
|
+
[exports.GrpcStatus.ABORTED]: 'ABORTED',
|
|
284
|
+
[exports.GrpcStatus.OUT_OF_RANGE]: 'OUT_OF_RANGE',
|
|
285
|
+
[exports.GrpcStatus.UNIMPLEMENTED]: 'UNIMPLEMENTED',
|
|
286
|
+
[exports.GrpcStatus.INTERNAL]: 'INTERNAL',
|
|
287
|
+
[exports.GrpcStatus.UNAVAILABLE]: 'UNAVAILABLE',
|
|
288
|
+
[exports.GrpcStatus.DATA_LOSS]: 'DATA_LOSS',
|
|
289
|
+
[exports.GrpcStatus.UNAUTHENTICATED]: 'UNAUTHENTICATED',
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Get human-readable name for a gRPC status code.
|
|
293
|
+
*/
|
|
294
|
+
function getStatusName(code) {
|
|
295
|
+
return exports.GrpcStatusName[code] ?? 'UNKNOWN';
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { WIRE_02_JWS_TYP } from '@peac/kernel';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { validateCarrierConstraints } from '@peac/schema';
|
|
4
|
+
|
|
5
|
+
// src/metadata.ts
|
|
6
|
+
var GrpcMetadataKeys = {
|
|
7
|
+
/** PEAC receipt in metadata */
|
|
8
|
+
RECEIPT: "peac-receipt",
|
|
9
|
+
/** PEAC receipt type */
|
|
10
|
+
RECEIPT_TYPE: "peac-receipt-type",
|
|
11
|
+
/** TAP signature */
|
|
12
|
+
TAP_SIGNATURE: "peac-tap-signature",
|
|
13
|
+
/** TAP signature input */
|
|
14
|
+
TAP_SIGNATURE_INPUT: "peac-tap-signature-input",
|
|
15
|
+
/** PEAC error code in trailer */
|
|
16
|
+
ERROR_CODE: "peac-error-code",
|
|
17
|
+
/** Request ID for tracing */
|
|
18
|
+
REQUEST_ID: "peac-request-id"
|
|
19
|
+
};
|
|
20
|
+
function extractReceiptFromMetadata(metadata) {
|
|
21
|
+
const receipt = metadata[GrpcMetadataKeys.RECEIPT];
|
|
22
|
+
if (typeof receipt === "string") {
|
|
23
|
+
return receipt;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(receipt) && receipt.length > 0) {
|
|
26
|
+
return receipt[0];
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function extractReceiptTypeFromMetadata(metadata) {
|
|
31
|
+
const typ = metadata[GrpcMetadataKeys.RECEIPT_TYPE];
|
|
32
|
+
if (typeof typ === "string") {
|
|
33
|
+
return typ;
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(typ) && typ.length > 0) {
|
|
36
|
+
return typ[0];
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function addReceiptToMetadata(metadata, receiptJws, receiptType = WIRE_02_JWS_TYP) {
|
|
41
|
+
metadata[GrpcMetadataKeys.RECEIPT] = receiptJws;
|
|
42
|
+
metadata[GrpcMetadataKeys.RECEIPT_TYPE] = receiptType;
|
|
43
|
+
}
|
|
44
|
+
var GRPC_MAX_CARRIER_SIZE = 8192;
|
|
45
|
+
var BINARY_SUFFIX = "-bin";
|
|
46
|
+
var A2AGrpcCarrierAdapter = class {
|
|
47
|
+
/**
|
|
48
|
+
* Extract PEAC evidence carrier from gRPC metadata.
|
|
49
|
+
*
|
|
50
|
+
* Computes the real SHA-256 receipt_ref from the JWS bytes using
|
|
51
|
+
* Node's synchronous crypto.createHash (server-first package).
|
|
52
|
+
* Rejects binary metadata keys (gRPC `-bin` suffix convention).
|
|
53
|
+
*
|
|
54
|
+
* @returns Extracted carrier with computed receipt_ref, or null if absent
|
|
55
|
+
*/
|
|
56
|
+
extract(input) {
|
|
57
|
+
const binaryReceiptKey = GrpcMetadataKeys.RECEIPT + BINARY_SUFFIX;
|
|
58
|
+
if (binaryReceiptKey in input) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const receiptJws = extractReceiptFromMetadata(input);
|
|
62
|
+
if (!receiptJws) return null;
|
|
63
|
+
const digest = createHash("sha256").update(receiptJws).digest("hex");
|
|
64
|
+
const receiptRef = `sha256:${digest}`;
|
|
65
|
+
const carrier = {
|
|
66
|
+
receipt_ref: receiptRef,
|
|
67
|
+
receipt_jws: receiptJws
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
receipts: [carrier],
|
|
71
|
+
meta: createGrpcCarrierMeta()
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
attach(output, carriers, meta) {
|
|
75
|
+
if (carriers.length === 0) return output;
|
|
76
|
+
const carrier = carriers[0];
|
|
77
|
+
const effectiveMeta = meta ?? createGrpcCarrierMeta();
|
|
78
|
+
const result = this.validateConstraints(carrier, effectiveMeta);
|
|
79
|
+
if (!result.valid) {
|
|
80
|
+
throw new Error(`Carrier constraint violation: ${result.violations.join("; ")}`);
|
|
81
|
+
}
|
|
82
|
+
if (carrier.receipt_jws) {
|
|
83
|
+
addReceiptToMetadata(output, carrier.receipt_jws);
|
|
84
|
+
}
|
|
85
|
+
return output;
|
|
86
|
+
}
|
|
87
|
+
validateConstraints(carrier, meta) {
|
|
88
|
+
return validateCarrierConstraints(carrier, meta);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
function createGrpcCarrierMeta(overrides) {
|
|
92
|
+
return {
|
|
93
|
+
transport: "grpc",
|
|
94
|
+
format: "embed",
|
|
95
|
+
max_size: GRPC_MAX_CARRIER_SIZE,
|
|
96
|
+
...overrides
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function validateOwnMetadataKeys() {
|
|
100
|
+
const ASCII_KEY_REGEX = /^[a-z0-9_-]+$/;
|
|
101
|
+
const RESERVED_PREFIX = "grpc-";
|
|
102
|
+
const invalid = [];
|
|
103
|
+
for (const key of Object.values(GrpcMetadataKeys)) {
|
|
104
|
+
if (!ASCII_KEY_REGEX.test(key)) {
|
|
105
|
+
invalid.push(key);
|
|
106
|
+
} else if (key.startsWith(RESERVED_PREFIX)) {
|
|
107
|
+
invalid.push(key);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return invalid;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/index.ts
|
|
114
|
+
var GRPC_TRANSPORT_VERSION = "0.12.6";
|
|
115
|
+
var GrpcStatus = {
|
|
116
|
+
/** Success */
|
|
117
|
+
OK: 0,
|
|
118
|
+
/** Operation was cancelled */
|
|
119
|
+
CANCELLED: 1,
|
|
120
|
+
/** Unknown error */
|
|
121
|
+
UNKNOWN: 2,
|
|
122
|
+
/** Client specified invalid argument */
|
|
123
|
+
INVALID_ARGUMENT: 3,
|
|
124
|
+
/** Deadline expired before operation completed */
|
|
125
|
+
DEADLINE_EXCEEDED: 4,
|
|
126
|
+
/** Requested entity not found */
|
|
127
|
+
NOT_FOUND: 5,
|
|
128
|
+
/** Entity already exists */
|
|
129
|
+
ALREADY_EXISTS: 6,
|
|
130
|
+
/** Caller lacks permission */
|
|
131
|
+
PERMISSION_DENIED: 7,
|
|
132
|
+
/** Resource exhausted */
|
|
133
|
+
RESOURCE_EXHAUSTED: 8,
|
|
134
|
+
/** Operation rejected due to precondition */
|
|
135
|
+
FAILED_PRECONDITION: 9,
|
|
136
|
+
/** Operation aborted (conflict) */
|
|
137
|
+
ABORTED: 10,
|
|
138
|
+
/** Value out of range */
|
|
139
|
+
OUT_OF_RANGE: 11,
|
|
140
|
+
/** Operation not implemented */
|
|
141
|
+
UNIMPLEMENTED: 12,
|
|
142
|
+
/** Internal error */
|
|
143
|
+
INTERNAL: 13,
|
|
144
|
+
/** Service unavailable */
|
|
145
|
+
UNAVAILABLE: 14,
|
|
146
|
+
/** Data loss */
|
|
147
|
+
DATA_LOSS: 15,
|
|
148
|
+
/** Not authenticated */
|
|
149
|
+
UNAUTHENTICATED: 16
|
|
150
|
+
};
|
|
151
|
+
function httpStatusToGrpc(httpStatus) {
|
|
152
|
+
switch (httpStatus) {
|
|
153
|
+
case 200:
|
|
154
|
+
case 201:
|
|
155
|
+
case 204:
|
|
156
|
+
return GrpcStatus.OK;
|
|
157
|
+
case 400:
|
|
158
|
+
return GrpcStatus.INVALID_ARGUMENT;
|
|
159
|
+
case 401:
|
|
160
|
+
return GrpcStatus.UNAUTHENTICATED;
|
|
161
|
+
case 402:
|
|
162
|
+
return GrpcStatus.FAILED_PRECONDITION;
|
|
163
|
+
case 403:
|
|
164
|
+
return GrpcStatus.PERMISSION_DENIED;
|
|
165
|
+
case 404:
|
|
166
|
+
return GrpcStatus.NOT_FOUND;
|
|
167
|
+
case 409:
|
|
168
|
+
return GrpcStatus.ABORTED;
|
|
169
|
+
case 429:
|
|
170
|
+
return GrpcStatus.RESOURCE_EXHAUSTED;
|
|
171
|
+
case 499:
|
|
172
|
+
return GrpcStatus.CANCELLED;
|
|
173
|
+
case 500:
|
|
174
|
+
return GrpcStatus.INTERNAL;
|
|
175
|
+
case 501:
|
|
176
|
+
return GrpcStatus.UNIMPLEMENTED;
|
|
177
|
+
case 503:
|
|
178
|
+
return GrpcStatus.UNAVAILABLE;
|
|
179
|
+
case 504:
|
|
180
|
+
return GrpcStatus.DEADLINE_EXCEEDED;
|
|
181
|
+
default:
|
|
182
|
+
if (httpStatus >= 400 && httpStatus < 500) {
|
|
183
|
+
return GrpcStatus.INVALID_ARGUMENT;
|
|
184
|
+
}
|
|
185
|
+
if (httpStatus >= 500) {
|
|
186
|
+
return GrpcStatus.INTERNAL;
|
|
187
|
+
}
|
|
188
|
+
return GrpcStatus.OK;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function grpcStatusToHttp(grpcStatus) {
|
|
192
|
+
switch (grpcStatus) {
|
|
193
|
+
case GrpcStatus.OK:
|
|
194
|
+
return 200;
|
|
195
|
+
case GrpcStatus.CANCELLED:
|
|
196
|
+
return 499;
|
|
197
|
+
case GrpcStatus.UNKNOWN:
|
|
198
|
+
return 500;
|
|
199
|
+
case GrpcStatus.INVALID_ARGUMENT:
|
|
200
|
+
return 400;
|
|
201
|
+
case GrpcStatus.DEADLINE_EXCEEDED:
|
|
202
|
+
return 504;
|
|
203
|
+
case GrpcStatus.NOT_FOUND:
|
|
204
|
+
return 404;
|
|
205
|
+
case GrpcStatus.ALREADY_EXISTS:
|
|
206
|
+
return 409;
|
|
207
|
+
case GrpcStatus.PERMISSION_DENIED:
|
|
208
|
+
return 403;
|
|
209
|
+
case GrpcStatus.RESOURCE_EXHAUSTED:
|
|
210
|
+
return 429;
|
|
211
|
+
case GrpcStatus.FAILED_PRECONDITION:
|
|
212
|
+
return 402;
|
|
213
|
+
case GrpcStatus.ABORTED:
|
|
214
|
+
return 409;
|
|
215
|
+
case GrpcStatus.OUT_OF_RANGE:
|
|
216
|
+
return 400;
|
|
217
|
+
case GrpcStatus.UNIMPLEMENTED:
|
|
218
|
+
return 501;
|
|
219
|
+
case GrpcStatus.INTERNAL:
|
|
220
|
+
return 500;
|
|
221
|
+
case GrpcStatus.UNAVAILABLE:
|
|
222
|
+
return 503;
|
|
223
|
+
case GrpcStatus.DATA_LOSS:
|
|
224
|
+
return 500;
|
|
225
|
+
case GrpcStatus.UNAUTHENTICATED:
|
|
226
|
+
return 401;
|
|
227
|
+
default:
|
|
228
|
+
return 500;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
var PEAC_ERROR_TO_GRPC = {
|
|
232
|
+
// 402 Payment Required -> FAILED_PRECONDITION
|
|
233
|
+
E_RECEIPT_MISSING: GrpcStatus.FAILED_PRECONDITION,
|
|
234
|
+
E_RECEIPT_INVALID: GrpcStatus.FAILED_PRECONDITION,
|
|
235
|
+
E_RECEIPT_EXPIRED: GrpcStatus.FAILED_PRECONDITION,
|
|
236
|
+
// 401 Unauthenticated -> UNAUTHENTICATED
|
|
237
|
+
E_TAP_SIGNATURE_MISSING: GrpcStatus.UNAUTHENTICATED,
|
|
238
|
+
E_TAP_SIGNATURE_INVALID: GrpcStatus.UNAUTHENTICATED,
|
|
239
|
+
E_TAP_TIME_INVALID: GrpcStatus.UNAUTHENTICATED,
|
|
240
|
+
E_TAP_KEY_NOT_FOUND: GrpcStatus.UNAUTHENTICATED,
|
|
241
|
+
E_TAP_REPLAY_PROTECTION_REQUIRED: GrpcStatus.UNAUTHENTICATED,
|
|
242
|
+
// 400 Bad Request -> INVALID_ARGUMENT
|
|
243
|
+
E_TAP_WINDOW_TOO_LARGE: GrpcStatus.INVALID_ARGUMENT,
|
|
244
|
+
E_TAP_TAG_UNKNOWN: GrpcStatus.INVALID_ARGUMENT,
|
|
245
|
+
E_TAP_ALGORITHM_INVALID: GrpcStatus.INVALID_ARGUMENT,
|
|
246
|
+
// 403 Forbidden -> PERMISSION_DENIED
|
|
247
|
+
E_ISSUER_NOT_ALLOWED: GrpcStatus.PERMISSION_DENIED,
|
|
248
|
+
// 409 Conflict -> ABORTED
|
|
249
|
+
E_TAP_NONCE_REPLAY: GrpcStatus.ABORTED,
|
|
250
|
+
// 500 Internal -> INTERNAL
|
|
251
|
+
E_CONFIG_ISSUER_ALLOWLIST_REQUIRED: GrpcStatus.INTERNAL,
|
|
252
|
+
E_INTERNAL_ERROR: GrpcStatus.INTERNAL
|
|
253
|
+
};
|
|
254
|
+
function peacErrorToGrpc(errorCode) {
|
|
255
|
+
return PEAC_ERROR_TO_GRPC[errorCode] ?? GrpcStatus.INTERNAL;
|
|
256
|
+
}
|
|
257
|
+
function createGrpcError(peacCode, message, details) {
|
|
258
|
+
return {
|
|
259
|
+
code: peacErrorToGrpc(peacCode),
|
|
260
|
+
message,
|
|
261
|
+
peacCode,
|
|
262
|
+
details
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function createSuccessResult(receiptId) {
|
|
266
|
+
return {
|
|
267
|
+
ok: true,
|
|
268
|
+
status: GrpcStatus.OK,
|
|
269
|
+
receiptId
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function createFailureResult(error) {
|
|
273
|
+
return {
|
|
274
|
+
ok: false,
|
|
275
|
+
status: error.code,
|
|
276
|
+
error
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
var GrpcStatusName = {
|
|
280
|
+
[GrpcStatus.OK]: "OK",
|
|
281
|
+
[GrpcStatus.CANCELLED]: "CANCELLED",
|
|
282
|
+
[GrpcStatus.UNKNOWN]: "UNKNOWN",
|
|
283
|
+
[GrpcStatus.INVALID_ARGUMENT]: "INVALID_ARGUMENT",
|
|
284
|
+
[GrpcStatus.DEADLINE_EXCEEDED]: "DEADLINE_EXCEEDED",
|
|
285
|
+
[GrpcStatus.NOT_FOUND]: "NOT_FOUND",
|
|
286
|
+
[GrpcStatus.ALREADY_EXISTS]: "ALREADY_EXISTS",
|
|
287
|
+
[GrpcStatus.PERMISSION_DENIED]: "PERMISSION_DENIED",
|
|
288
|
+
[GrpcStatus.RESOURCE_EXHAUSTED]: "RESOURCE_EXHAUSTED",
|
|
289
|
+
[GrpcStatus.FAILED_PRECONDITION]: "FAILED_PRECONDITION",
|
|
290
|
+
[GrpcStatus.ABORTED]: "ABORTED",
|
|
291
|
+
[GrpcStatus.OUT_OF_RANGE]: "OUT_OF_RANGE",
|
|
292
|
+
[GrpcStatus.UNIMPLEMENTED]: "UNIMPLEMENTED",
|
|
293
|
+
[GrpcStatus.INTERNAL]: "INTERNAL",
|
|
294
|
+
[GrpcStatus.UNAVAILABLE]: "UNAVAILABLE",
|
|
295
|
+
[GrpcStatus.DATA_LOSS]: "DATA_LOSS",
|
|
296
|
+
[GrpcStatus.UNAUTHENTICATED]: "UNAUTHENTICATED"
|
|
297
|
+
};
|
|
298
|
+
function getStatusName(code) {
|
|
299
|
+
return GrpcStatusName[code] ?? "UNKNOWN";
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export { A2AGrpcCarrierAdapter, GRPC_MAX_CARRIER_SIZE, GRPC_TRANSPORT_VERSION, GrpcMetadataKeys, GrpcStatus, GrpcStatusName, PEAC_ERROR_TO_GRPC, addReceiptToMetadata, createFailureResult, createGrpcCarrierMeta, createGrpcError, createSuccessResult, extractReceiptFromMetadata, extractReceiptTypeFromMetadata, getStatusName, grpcStatusToHttp, httpStatusToGrpc, peacErrorToGrpc, validateOwnMetadataKeys };
|
|
303
|
+
//# sourceMappingURL=index.mjs.map
|
|
304
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/metadata.ts","../src/a2a-carrier.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * gRPC metadata keys, types, and helpers for PEAC transport.\n *\n * Extracted to a separate module to avoid circular imports between\n * index.ts and a2a-carrier.ts.\n */\n\nimport { WIRE_02_JWS_TYP } from '@peac/kernel';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** gRPC metadata shape for PEAC carrier operations */\nexport type GrpcMetadataLike = Record<string, string | string[] | undefined>;\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * gRPC metadata keys for PEAC transport.\n */\nexport const GrpcMetadataKeys = {\n /** PEAC receipt in metadata */\n RECEIPT: 'peac-receipt',\n /** PEAC receipt type */\n RECEIPT_TYPE: 'peac-receipt-type',\n /** TAP signature */\n TAP_SIGNATURE: 'peac-tap-signature',\n /** TAP signature input */\n TAP_SIGNATURE_INPUT: 'peac-tap-signature-input',\n /** PEAC error code in trailer */\n ERROR_CODE: 'peac-error-code',\n /** Request ID for tracing */\n REQUEST_ID: 'peac-request-id',\n} as const;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract PEAC receipt from gRPC metadata.\n */\nexport function extractReceiptFromMetadata(metadata: GrpcMetadataLike): string | null {\n const receipt = metadata[GrpcMetadataKeys.RECEIPT];\n if (typeof receipt === 'string') {\n return receipt;\n }\n if (Array.isArray(receipt) && receipt.length > 0) {\n return receipt[0];\n }\n return null;\n}\n\n/**\n * Extract receipt type from gRPC metadata.\n */\nexport function extractReceiptTypeFromMetadata(metadata: GrpcMetadataLike): string | null {\n const typ = metadata[GrpcMetadataKeys.RECEIPT_TYPE];\n if (typeof typ === 'string') {\n return typ;\n }\n if (Array.isArray(typ) && typ.length > 0) {\n return typ[0];\n }\n return null;\n}\n\n/**\n * Add PEAC receipt to gRPC metadata.\n *\n * @param metadata - gRPC metadata object to modify\n * @param receiptJws - Compact JWS of the signed receipt\n * @param receiptType - Receipt typ value (defaults to Wire 0.2 `interaction-record+jwt`)\n */\nexport function addReceiptToMetadata(\n metadata: Record<string, string | string[]>,\n receiptJws: string,\n receiptType: string = WIRE_02_JWS_TYP\n): void {\n metadata[GrpcMetadataKeys.RECEIPT] = receiptJws;\n metadata[GrpcMetadataKeys.RECEIPT_TYPE] = receiptType;\n}\n","/**\n * gRPC CarrierAdapter for A2A transport.\n *\n * Implements the PEAC CarrierAdapter interface for gRPC metadata,\n * enabling receipt attach/extract via gRPC metadata keys. Pure TS\n * with no @grpc/grpc-js dependency; consumers bring their own gRPC.\n *\n * Size default: 8 KiB. gRPC metadata rides in HTTP/2 headers where\n * servers commonly enforce an 8 KiB limit. For larger receipts, use\n * reference mode (receipt_url) or negotiate a higher limit with the\n * gRPC server configuration.\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type {\n CarrierAdapter,\n PeacEvidenceCarrier,\n CarrierMeta,\n CarrierValidationResult,\n ReceiptRef,\n} from '@peac/kernel';\nimport { validateCarrierConstraints } from '@peac/schema';\n\nimport { GrpcMetadataKeys, extractReceiptFromMetadata, addReceiptToMetadata } from './metadata.js';\nimport type { GrpcMetadataLike } from './metadata.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * Default maximum carrier size for gRPC metadata (8 KiB).\n *\n * gRPC metadata is carried in HTTP/2 headers. Official gRPC guidance\n * warns that servers may limit request headers, with a common default\n * of 8 KiB. This is a conservative interoperability-safe default.\n * Consumers with known larger server limits can override via\n * `createGrpcCarrierMeta({ max_size: ... })`.\n */\nexport const GRPC_MAX_CARRIER_SIZE = 8_192;\n\n/** Binary metadata key suffix per gRPC convention */\nconst BINARY_SUFFIX = '-bin';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * CarrierAdapter for gRPC metadata transport.\n *\n * Reads and writes PEAC evidence carriers via `GrpcMetadataKeys.RECEIPT`\n * and `GrpcMetadataKeys.RECEIPT_TYPE` metadata entries.\n *\n * `extract()` computes the real SHA-256 receipt_ref synchronously\n * using Node's `crypto.createHash` (server-first package).\n */\nexport class A2AGrpcCarrierAdapter implements CarrierAdapter<GrpcMetadataLike, GrpcMetadataLike> {\n /**\n * Extract PEAC evidence carrier from gRPC metadata.\n *\n * Computes the real SHA-256 receipt_ref from the JWS bytes using\n * Node's synchronous crypto.createHash (server-first package).\n * Rejects binary metadata keys (gRPC `-bin` suffix convention).\n *\n * @returns Extracted carrier with computed receipt_ref, or null if absent\n */\n extract(input: GrpcMetadataLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {\n // Reject binary-encoded PEAC receipt metadata\n const binaryReceiptKey = GrpcMetadataKeys.RECEIPT + BINARY_SUFFIX;\n if (binaryReceiptKey in input) {\n return null;\n }\n\n const receiptJws = extractReceiptFromMetadata(input);\n if (!receiptJws) return null;\n\n const digest = createHash('sha256').update(receiptJws).digest('hex');\n const receiptRef = `sha256:${digest}` as ReceiptRef;\n\n const carrier: PeacEvidenceCarrier = {\n receipt_ref: receiptRef,\n receipt_jws: receiptJws,\n };\n\n return {\n receipts: [carrier],\n meta: createGrpcCarrierMeta(),\n };\n }\n\n attach(\n output: GrpcMetadataLike,\n carriers: PeacEvidenceCarrier[],\n meta?: CarrierMeta\n ): GrpcMetadataLike {\n if (carriers.length === 0) return output;\n\n const carrier = carriers[0];\n const effectiveMeta = meta ?? createGrpcCarrierMeta();\n const result = this.validateConstraints(carrier, effectiveMeta);\n if (!result.valid) {\n throw new Error(`Carrier constraint violation: ${result.violations.join('; ')}`);\n }\n\n if (carrier.receipt_jws) {\n addReceiptToMetadata(output as Record<string, string | string[]>, carrier.receipt_jws);\n }\n\n return output;\n }\n\n validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {\n return validateCarrierConstraints(carrier, meta);\n }\n}\n\n/**\n * Create default CarrierMeta for gRPC transport.\n *\n * Default max_size is 8 KiB (HTTP/2 header budget). Override for\n * environments with known larger server limits.\n */\nexport function createGrpcCarrierMeta(overrides?: Partial<CarrierMeta>): CarrierMeta {\n return {\n transport: 'grpc',\n format: 'embed',\n max_size: GRPC_MAX_CARRIER_SIZE,\n ...overrides,\n };\n}\n\n/**\n * Validate that the package's own PEAC metadata key constants are ASCII-safe\n * and do not use the reserved `grpc-` prefix.\n *\n * This is a repo-level invariant check, not an inbound metadata validator.\n * It verifies that all keys defined in `GrpcMetadataKeys` use only\n * lowercase ASCII letters, digits, hyphens, and underscores per\n * gRPC metadata key requirements, and that none start with the\n * reserved `grpc-` prefix.\n *\n * @returns Array of invalid keys (empty if all valid)\n */\nexport function validateOwnMetadataKeys(): string[] {\n const ASCII_KEY_REGEX = /^[a-z0-9_-]+$/;\n const RESERVED_PREFIX = 'grpc-';\n const invalid: string[] = [];\n for (const key of Object.values(GrpcMetadataKeys)) {\n if (!ASCII_KEY_REGEX.test(key)) {\n invalid.push(key);\n } else if (key.startsWith(RESERVED_PREFIX)) {\n invalid.push(key);\n }\n }\n return invalid;\n}\n","/**\n * PEAC gRPC Transport Layer\n *\n * Provides gRPC binding for PEAC receipts with StatusCode parity to HTTP.\n *\n * Status code mapping follows these semantics:\n * - INVALID_ARGUMENT (3): Malformed request (HTTP 400)\n * - UNAUTHENTICATED (16): Authentication required (HTTP 401)\n * - FAILED_PRECONDITION (9): Payment required (HTTP 402)\n * - PERMISSION_DENIED (7): Not authorized (HTTP 403)\n * - ABORTED (10): Conflict/replay detected (HTTP 409)\n * - INTERNAL (13): Server error (HTTP 500)\n *\n * @packageDocumentation\n */\n\nexport const GRPC_TRANSPORT_VERSION = '0.12.6' as const;\n\n// Metadata keys, types, and helpers (shared with a2a-carrier.ts)\nexport {\n GrpcMetadataKeys,\n extractReceiptFromMetadata,\n extractReceiptTypeFromMetadata,\n addReceiptToMetadata,\n} from './metadata.js';\nexport type { GrpcMetadataLike } from './metadata.js';\n\n/**\n * gRPC status codes.\n * @see https://grpc.io/docs/guides/status-codes/\n */\nexport const GrpcStatus = {\n /** Success */\n OK: 0,\n /** Operation was cancelled */\n CANCELLED: 1,\n /** Unknown error */\n UNKNOWN: 2,\n /** Client specified invalid argument */\n INVALID_ARGUMENT: 3,\n /** Deadline expired before operation completed */\n DEADLINE_EXCEEDED: 4,\n /** Requested entity not found */\n NOT_FOUND: 5,\n /** Entity already exists */\n ALREADY_EXISTS: 6,\n /** Caller lacks permission */\n PERMISSION_DENIED: 7,\n /** Resource exhausted */\n RESOURCE_EXHAUSTED: 8,\n /** Operation rejected due to precondition */\n FAILED_PRECONDITION: 9,\n /** Operation aborted (conflict) */\n ABORTED: 10,\n /** Value out of range */\n OUT_OF_RANGE: 11,\n /** Operation not implemented */\n UNIMPLEMENTED: 12,\n /** Internal error */\n INTERNAL: 13,\n /** Service unavailable */\n UNAVAILABLE: 14,\n /** Data loss */\n DATA_LOSS: 15,\n /** Not authenticated */\n UNAUTHENTICATED: 16,\n} as const;\n\nexport type GrpcStatusCode = (typeof GrpcStatus)[keyof typeof GrpcStatus];\n\n/**\n * Map HTTP status code to gRPC status code.\n *\n * Mapping semantics:\n * - 400 Bad Request -> INVALID_ARGUMENT (malformed)\n * - 401 Unauthorized -> UNAUTHENTICATED (auth required)\n * - 402 Payment Required -> FAILED_PRECONDITION (payment needed)\n * - 403 Forbidden -> PERMISSION_DENIED (not authorized)\n * - 409 Conflict -> ABORTED (replay detected)\n * - 500 Internal Server Error -> INTERNAL\n * - Other 4xx -> INVALID_ARGUMENT\n * - Other 5xx -> INTERNAL\n */\nexport function httpStatusToGrpc(httpStatus: number): GrpcStatusCode {\n switch (httpStatus) {\n case 200:\n case 201:\n case 204:\n return GrpcStatus.OK;\n case 400:\n return GrpcStatus.INVALID_ARGUMENT;\n case 401:\n return GrpcStatus.UNAUTHENTICATED;\n case 402:\n return GrpcStatus.FAILED_PRECONDITION;\n case 403:\n return GrpcStatus.PERMISSION_DENIED;\n case 404:\n return GrpcStatus.NOT_FOUND;\n case 409:\n return GrpcStatus.ABORTED;\n case 429:\n return GrpcStatus.RESOURCE_EXHAUSTED;\n case 499:\n return GrpcStatus.CANCELLED;\n case 500:\n return GrpcStatus.INTERNAL;\n case 501:\n return GrpcStatus.UNIMPLEMENTED;\n case 503:\n return GrpcStatus.UNAVAILABLE;\n case 504:\n return GrpcStatus.DEADLINE_EXCEEDED;\n default:\n if (httpStatus >= 400 && httpStatus < 500) {\n return GrpcStatus.INVALID_ARGUMENT;\n }\n if (httpStatus >= 500) {\n return GrpcStatus.INTERNAL;\n }\n return GrpcStatus.OK;\n }\n}\n\n/**\n * Map gRPC status code to HTTP status code.\n *\n * Inverse of httpStatusToGrpc for response translation.\n */\nexport function grpcStatusToHttp(grpcStatus: GrpcStatusCode): number {\n switch (grpcStatus) {\n case GrpcStatus.OK:\n return 200;\n case GrpcStatus.CANCELLED:\n return 499;\n case GrpcStatus.UNKNOWN:\n return 500;\n case GrpcStatus.INVALID_ARGUMENT:\n return 400;\n case GrpcStatus.DEADLINE_EXCEEDED:\n return 504;\n case GrpcStatus.NOT_FOUND:\n return 404;\n case GrpcStatus.ALREADY_EXISTS:\n return 409;\n case GrpcStatus.PERMISSION_DENIED:\n return 403;\n case GrpcStatus.RESOURCE_EXHAUSTED:\n return 429;\n case GrpcStatus.FAILED_PRECONDITION:\n return 402;\n case GrpcStatus.ABORTED:\n return 409;\n case GrpcStatus.OUT_OF_RANGE:\n return 400;\n case GrpcStatus.UNIMPLEMENTED:\n return 501;\n case GrpcStatus.INTERNAL:\n return 500;\n case GrpcStatus.UNAVAILABLE:\n return 503;\n case GrpcStatus.DATA_LOSS:\n return 500;\n case GrpcStatus.UNAUTHENTICATED:\n return 401;\n default:\n return 500;\n }\n}\n\n/**\n * PEAC error code to gRPC status mapping.\n *\n * Maps canonical PEAC error codes to appropriate gRPC status codes.\n */\nexport const PEAC_ERROR_TO_GRPC: Record<string, GrpcStatusCode> = {\n // 402 Payment Required -> FAILED_PRECONDITION\n E_RECEIPT_MISSING: GrpcStatus.FAILED_PRECONDITION,\n E_RECEIPT_INVALID: GrpcStatus.FAILED_PRECONDITION,\n E_RECEIPT_EXPIRED: GrpcStatus.FAILED_PRECONDITION,\n\n // 401 Unauthenticated -> UNAUTHENTICATED\n E_TAP_SIGNATURE_MISSING: GrpcStatus.UNAUTHENTICATED,\n E_TAP_SIGNATURE_INVALID: GrpcStatus.UNAUTHENTICATED,\n E_TAP_TIME_INVALID: GrpcStatus.UNAUTHENTICATED,\n E_TAP_KEY_NOT_FOUND: GrpcStatus.UNAUTHENTICATED,\n E_TAP_REPLAY_PROTECTION_REQUIRED: GrpcStatus.UNAUTHENTICATED,\n\n // 400 Bad Request -> INVALID_ARGUMENT\n E_TAP_WINDOW_TOO_LARGE: GrpcStatus.INVALID_ARGUMENT,\n E_TAP_TAG_UNKNOWN: GrpcStatus.INVALID_ARGUMENT,\n E_TAP_ALGORITHM_INVALID: GrpcStatus.INVALID_ARGUMENT,\n\n // 403 Forbidden -> PERMISSION_DENIED\n E_ISSUER_NOT_ALLOWED: GrpcStatus.PERMISSION_DENIED,\n\n // 409 Conflict -> ABORTED\n E_TAP_NONCE_REPLAY: GrpcStatus.ABORTED,\n\n // 500 Internal -> INTERNAL\n E_CONFIG_ISSUER_ALLOWLIST_REQUIRED: GrpcStatus.INTERNAL,\n E_INTERNAL_ERROR: GrpcStatus.INTERNAL,\n};\n\n/**\n * Get gRPC status for a PEAC error code.\n */\nexport function peacErrorToGrpc(errorCode: string): GrpcStatusCode {\n return PEAC_ERROR_TO_GRPC[errorCode] ?? GrpcStatus.INTERNAL;\n}\n\n/**\n * gRPC error with status code.\n */\nexport interface GrpcError {\n /** gRPC status code */\n code: GrpcStatusCode;\n /** Error message */\n message: string;\n /** PEAC error code (if applicable) */\n peacCode?: string;\n /** Additional error details */\n details?: unknown;\n}\n\n/**\n * Create a gRPC error from a PEAC error code.\n */\nexport function createGrpcError(peacCode: string, message: string, details?: unknown): GrpcError {\n return {\n code: peacErrorToGrpc(peacCode),\n message,\n peacCode,\n details,\n };\n}\n\n/**\n * gRPC verification result.\n */\nexport interface GrpcVerificationResult {\n /** Whether verification succeeded */\n ok: boolean;\n /** gRPC status code */\n status: GrpcStatusCode;\n /** Error if verification failed */\n error?: GrpcError;\n /** Receipt ID if verification succeeded */\n receiptId?: string;\n}\n\n/**\n * Create a successful verification result.\n */\nexport function createSuccessResult(receiptId?: string): GrpcVerificationResult {\n return {\n ok: true,\n status: GrpcStatus.OK,\n receiptId,\n };\n}\n\n/**\n * Create a failed verification result.\n */\nexport function createFailureResult(error: GrpcError): GrpcVerificationResult {\n return {\n ok: false,\n status: error.code,\n error,\n };\n}\n\n/**\n * Status code name mapping for debugging.\n */\nexport const GrpcStatusName: Record<GrpcStatusCode, string> = {\n [GrpcStatus.OK]: 'OK',\n [GrpcStatus.CANCELLED]: 'CANCELLED',\n [GrpcStatus.UNKNOWN]: 'UNKNOWN',\n [GrpcStatus.INVALID_ARGUMENT]: 'INVALID_ARGUMENT',\n [GrpcStatus.DEADLINE_EXCEEDED]: 'DEADLINE_EXCEEDED',\n [GrpcStatus.NOT_FOUND]: 'NOT_FOUND',\n [GrpcStatus.ALREADY_EXISTS]: 'ALREADY_EXISTS',\n [GrpcStatus.PERMISSION_DENIED]: 'PERMISSION_DENIED',\n [GrpcStatus.RESOURCE_EXHAUSTED]: 'RESOURCE_EXHAUSTED',\n [GrpcStatus.FAILED_PRECONDITION]: 'FAILED_PRECONDITION',\n [GrpcStatus.ABORTED]: 'ABORTED',\n [GrpcStatus.OUT_OF_RANGE]: 'OUT_OF_RANGE',\n [GrpcStatus.UNIMPLEMENTED]: 'UNIMPLEMENTED',\n [GrpcStatus.INTERNAL]: 'INTERNAL',\n [GrpcStatus.UNAVAILABLE]: 'UNAVAILABLE',\n [GrpcStatus.DATA_LOSS]: 'DATA_LOSS',\n [GrpcStatus.UNAUTHENTICATED]: 'UNAUTHENTICATED',\n};\n\n/**\n * Get human-readable name for a gRPC status code.\n */\nexport function getStatusName(code: GrpcStatusCode): string {\n return GrpcStatusName[code] ?? 'UNKNOWN';\n}\n\n// ---------------------------------------------------------------------------\n// Carrier adapter re-exports\n// ---------------------------------------------------------------------------\n\nexport {\n A2AGrpcCarrierAdapter,\n createGrpcCarrierMeta,\n validateOwnMetadataKeys,\n GRPC_MAX_CARRIER_SIZE,\n} from './a2a-carrier.js';\n"]}
|