@virtru/dsp-sdk 0.2.3 → 0.3.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.
Files changed (33) hide show
  1. package/.rush/temp/chunked-rush-logs/dsp-sdk._phase_build.chunks.jsonl +3 -3
  2. package/.rush/temp/chunked-rush-logs/dsp-sdk._phase_test.chunks.jsonl +37 -9
  3. package/.rush/temp/package-deps__phase_build.json +16 -8
  4. package/.rush/temp/shrinkwrap-deps.json +39 -35
  5. package/CHANGELOG.json +28 -0
  6. package/CHANGELOG.md +15 -1
  7. package/README.md +55 -0
  8. package/buf.gen.yaml +17 -0
  9. package/buf.yaml +4 -0
  10. package/dist/src/gen/virtru/common/common_pb.d.ts +151 -0
  11. package/dist/src/gen/virtru/common/common_pb.js +57 -0
  12. package/dist/src/gen/virtru/policy/certificates/v1/certificates_pb.d.ts +215 -0
  13. package/dist/src/gen/virtru/policy/certificates/v1/certificates_pb.js +50 -0
  14. package/dist/src/gen/virtru/policy/objects_pb.d.ts +188 -0
  15. package/dist/src/gen/virtru/policy/objects_pb.js +126 -0
  16. package/dist/src/index.d.ts +1 -1
  17. package/dist/src/index.js +1 -1
  18. package/dist/src/lib/client.d.ts +2 -0
  19. package/dist/src/lib/client.js +2 -0
  20. package/dist/src/lib/consts.d.ts +2 -0
  21. package/dist/src/lib/consts.js +7 -0
  22. package/dist/src/lib/utils.d.ts +136 -0
  23. package/dist/src/lib/utils.js +355 -2
  24. package/package.json +5 -3
  25. package/src/gen/virtru/common/common_pb.ts +179 -0
  26. package/src/gen/virtru/policy/certificates/v1/certificates_connect.ts +44 -0
  27. package/src/gen/virtru/policy/certificates/v1/certificates_pb.ts +260 -0
  28. package/src/gen/virtru/policy/objects_pb.ts +235 -0
  29. package/src/index.ts +15 -1
  30. package/src/lib/client.ts +3 -0
  31. package/src/lib/consts.ts +8 -0
  32. package/src/lib/utils.test.ts +376 -0
  33. package/src/lib/utils.ts +460 -4
@@ -3,6 +3,13 @@
3
3
  *
4
4
  * Your use of this file is governed by the Virtu Terms of Service <https://www.virtru.com/terms-of-service/>.
5
5
  */
6
+ import { AuthProviders, OpenTDF, PermissionDeniedError } from '@opentdf/sdk';
7
+ import { PlatformClient } from '@opentdf/sdk/platform';
8
+ import { ActiveStateEnum } from '@opentdf/sdk/platform/common/common_pb.js';
9
+ import * as asn1js from 'asn1js';
10
+ import * as pkijs from 'pkijs';
11
+ import { MAX_CERT_BYTES, MAX_CERTS } from "./consts";
12
+ import { DSPClient } from './client';
6
13
  /**
7
14
  * Creates an interceptor that adds authentication headers to outgoing requests.
8
15
  *
@@ -15,7 +22,7 @@
15
22
  * @returns An `Interceptor` function that modifies requests to include authentication headers.
16
23
  */
17
24
  export function createAuthInterceptor(authProvider) {
18
- const authInterceptor = (next) => async (req) => {
25
+ return (next) => async (req) => {
19
26
  const url = new URL(req.url);
20
27
  const pathOnly = url.pathname;
21
28
  // Signs only the path of the url in the request
@@ -31,5 +38,351 @@ export function createAuthInterceptor(authProvider) {
31
38
  });
32
39
  return await next(req);
33
40
  };
34
- return authInterceptor;
41
+ }
42
+ /** Creates a new instance of an OIDC Auth Provider consumed by the TDF Clients */
43
+ export async function createAuthProvider(options) {
44
+ const { oidc, refreshToken } = options;
45
+ return await AuthProviders.refreshAuthProvider({
46
+ clientId: oidc.clientId,
47
+ exchange: 'refresh',
48
+ refreshToken: refreshToken,
49
+ // TODO(DSPX-1559): Clean up these URLs.
50
+ oidcOrigin: 'https://only-required-for-back-compat.invalid',
51
+ oidcTokenEndpoint: oidc.tokenEndpoint,
52
+ oidcUserInfoEndpoint: oidc.userInfoEndpoint,
53
+ });
54
+ }
55
+ export async function createOpenTDFClient(options) {
56
+ const { platformEndpoint, obligations, ...authProviderOptions } = options;
57
+ return new OpenTDF({
58
+ authProvider: await createAuthProvider(authProviderOptions),
59
+ platformUrl: platformEndpoint,
60
+ policyEndpoint: platformEndpoint,
61
+ defaultCreateOptions: {
62
+ defaultKASEndpoint: `${platformEndpoint}/kas`,
63
+ },
64
+ defaultReadOptions: {
65
+ fulfillableObligationFQNs: obligations,
66
+ // NOTE(DSP-249): Disabling assertion verification until all generated assertions are supported.
67
+ noVerify: true,
68
+ },
69
+ disableDPoP: true,
70
+ });
71
+ }
72
+ export const getObligations = async (ciphertext, options) => {
73
+ const client = await createOpenTDFClient(options);
74
+ const source = {
75
+ type: 'buffer',
76
+ location: new Uint8Array(ciphertext),
77
+ };
78
+ const tdfReader = client.open({ source });
79
+ let obligations = [];
80
+ try {
81
+ obligations = (await tdfReader.obligations()).fqns;
82
+ }
83
+ catch (error) {
84
+ if (error instanceof PermissionDeniedError) {
85
+ obligations = error.requiredObligations || [];
86
+ }
87
+ // Swallow other errors and return empty obligations.
88
+ }
89
+ return obligations;
90
+ };
91
+ export async function getUserEntitlements(options) {
92
+ const authProvider = await createAuthProvider({
93
+ oidc: options.oidc,
94
+ refreshToken: options.refreshToken,
95
+ });
96
+ const accessToken = await authProvider.oidcAuth.get();
97
+ const userEntitlementsResponse = await fetch(`${options.platformEndpoint}/shared/entitlements`, {
98
+ body: JSON.stringify({}),
99
+ headers: {
100
+ Authorization: `Bearer ${accessToken}`,
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ method: 'POST',
104
+ });
105
+ return (await userEntitlementsResponse.json());
106
+ }
107
+ export const flattenObligations = (obligations) => Object.values(obligations).flatMap((feature) => feature?.fully_qualified_names || []);
108
+ /**
109
+ * Helper function to retrieve certificates for a specific namespace with pagination handling.
110
+ *
111
+ * This function automatically handles pagination to retrieve all certificates for a namespace,
112
+ * making multiple requests if necessary.
113
+ *
114
+ * @param dspClient - The DSP client instance.
115
+ * @param namespaceId - The namespace UUID.
116
+ * @returns A promise that resolves to an array of certificates for the namespace.
117
+ * @throws If there is an error retrieving the certificates from the CertificateService.
118
+ */
119
+ async function getCertificatesForNamespace(dspClient, namespaceId) {
120
+ const certificates = [];
121
+ let offset = 0;
122
+ const limit = 100;
123
+ while (true) {
124
+ const response = await dspClient.v1.certificateService.listCertificatesByNamespace({
125
+ namespaceId,
126
+ pagination: { limit, offset },
127
+ });
128
+ if (response.certificates?.length > 0) {
129
+ certificates.push(...response.certificates);
130
+ }
131
+ // Check for more pages
132
+ if (response.pagination?.nextOffset && response.pagination.nextOffset > 0) {
133
+ offset = response.pagination.nextOffset;
134
+ }
135
+ else {
136
+ break;
137
+ }
138
+ }
139
+ return certificates;
140
+ }
141
+ /**
142
+ * Retrieves all trusted certificates from active namespaces in the platform.
143
+ *
144
+ * This function uses the new CertificateService API to retrieve certificates from all active
145
+ * namespaces. It automatically handles pagination to ensure all certificates are retrieved.
146
+ *
147
+ * The function performs the following steps:
148
+ * 1. Creates an authenticated auth provider with DPoP signing keys
149
+ * 2. Lists all active namespaces using the PlatformClient
150
+ * 3. For each namespace, retrieves all associated certificates using the CertificateService
151
+ * 4. Aggregates and returns all certificates from all namespaces
152
+ *
153
+ * @param options - The options object containing the platform endpoint, OIDC configuration, and refresh token.
154
+ * @param options.oidc - The OIDC configuration object.
155
+ * @param options.oidc.clientId - The OIDC client ID.
156
+ * @param options.oidc.tokenEndpoint - The OIDC token endpoint URL.
157
+ * @param options.oidc.userInfoEndpoint - The OIDC user info endpoint URL.
158
+ * @param options.platformEndpoint - The base URL of the platform.
159
+ * @param options.refreshToken - The refresh token for authentication.
160
+ * @returns A promise that resolves to an array of trusted certificates from all active namespaces.
161
+ * @throws If there is an error retrieving namespaces or certificates.
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const certificates = await getTrustedCertificates({
166
+ * oidc: {
167
+ * clientId: 'my-client-id',
168
+ * tokenEndpoint: 'https://auth.example.com/token',
169
+ * userInfoEndpoint: 'https://auth.example.com/userinfo',
170
+ * },
171
+ * platformEndpoint: 'https://platform.example.com',
172
+ * refreshToken: 'my-refresh-token',
173
+ * });
174
+ * ```
175
+ */
176
+ export async function getTrustedCertificates(options) {
177
+ function generateSigningKeyPair() {
178
+ return crypto.subtle.generateKey({
179
+ name: 'ECDSA',
180
+ namedCurve: 'P-256',
181
+ }, true, ['sign', 'verify']);
182
+ }
183
+ const authProvider = await createAuthProvider({
184
+ oidc: options.oidc,
185
+ refreshToken: options.refreshToken,
186
+ });
187
+ await authProvider.updateClientPublicKey(await generateSigningKeyPair());
188
+ // Create both clients
189
+ const platform = new PlatformClient({
190
+ authProvider,
191
+ platformUrl: options.platformEndpoint,
192
+ });
193
+ const dspClient = new DSPClient({
194
+ platformUrl: options.platformEndpoint,
195
+ authProvider,
196
+ });
197
+ const certificates = [];
198
+ try {
199
+ // Get active namespaces (still using namespace API)
200
+ const namespaces = await platform.v1.namespace.listNamespaces({
201
+ state: ActiveStateEnum.ACTIVE,
202
+ });
203
+ // Get certificates using new CertificateService API
204
+ for (const namespace of namespaces.namespaces) {
205
+ const namespaceCerts = await getCertificatesForNamespace(dspClient, namespace.id);
206
+ certificates.push(...namespaceCerts);
207
+ }
208
+ }
209
+ catch (error) {
210
+ console.error('Error retrieving namespace certificates:', error);
211
+ throw error;
212
+ }
213
+ return certificates;
214
+ }
215
+ /**
216
+ * Helper to get a string representation of a pkijs Name.
217
+ */
218
+ function getNameStringSafe(name) {
219
+ if (!name)
220
+ return '';
221
+ try {
222
+ // pkijs Name to string can be derived from typesAndValues
223
+ const parts = (name.typesAndValues || []).map((tv) => {
224
+ const type = tv?.type ?? 'unknownType';
225
+ // tv.value is an ASN.1 value; best-effort toString fallback
226
+ let value;
227
+ try {
228
+ const block = tv?.value?.valueBlock;
229
+ const v = block?.value;
230
+ value = typeof v === 'string' ? v : String(tv?.value);
231
+ }
232
+ catch {
233
+ value = '<?>';
234
+ }
235
+ return `${type}=${value}`;
236
+ });
237
+ return parts.join(', ');
238
+ }
239
+ catch {
240
+ return '';
241
+ }
242
+ }
243
+ function base64ToArrayBuffer(b64) {
244
+ const normalized = b64.replace(/\s+/g, '');
245
+ // Basic sanity check; allow trailing '=' padding
246
+ if (!/^[-A-Za-z0-9+/]*=*$/.test(normalized)) {
247
+ throw new Error('Invalid base64 characters');
248
+ }
249
+ // Optional size guard (approx: 3/4 of base64 length is bytes)
250
+ const approxBytes = Math.floor((normalized.length * 3) / 4);
251
+ if (approxBytes === 0) {
252
+ throw new Error('Empty base64 data');
253
+ }
254
+ if (approxBytes > MAX_CERT_BYTES) {
255
+ throw new Error(`Certificate exceeds maximum allowed size of ${MAX_CERT_BYTES} bytes`);
256
+ }
257
+ const binaryString = atob(normalized);
258
+ const bytes = new Uint8Array(binaryString.length);
259
+ for (let i = 0; i < binaryString.length; i++) {
260
+ bytes[i] = binaryString.charCodeAt(i);
261
+ }
262
+ return bytes.buffer; // bytes is freshly allocated; buffer is tightly packed
263
+ }
264
+ function pemToArrayBuffer(pem) {
265
+ const base64Der = pem
266
+ .replace(/-----BEGIN CERTIFICATE-----/g, '')
267
+ .replace(/-----END CERTIFICATE-----/g, '')
268
+ .replace(/\r?\n|\r|\s/g, '');
269
+ return base64ToArrayBuffer(base64Der);
270
+ }
271
+ /**
272
+ * Validate that a certificate chain from JWS x5c header chains to a trusted root.
273
+ *
274
+ * This function is designed to be portable and can be moved to another repository.
275
+ * It validates that the certificate chain presented in a JWS x5c header builds a
276
+ * valid chain to one of the provided trusted root certificates.
277
+ *
278
+ * Expectations and behavior:
279
+ * - `x5c` must be ordered leaf-first and contain base64-encoded DER certs.
280
+ * - `trustedRootCertificates` should contain PEM-encoded root certificates.
281
+ * - Performs basic input size checks and safe base64 decoding.
282
+ * - Uses PKI.js `CertificateChainValidationEngine` for comprehensive path validation
283
+ * (validity dates, signatures, policies when present, etc.).
284
+ * - Returns detailed error messages including the leaf subject/issuer and parsing warnings.
285
+ *
286
+ * @param x5c - Array of base64-encoded DER certificates from JWS header (leaf first)
287
+ * @param trustedRootCertificates - Array of Certificate objects containing trusted roots in PEM format
288
+ * @returns Object with validation result and warnings
289
+ * @throws {Error} if validation fails
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * try {
294
+ * const result = await validateJWSCertificateChain(
295
+ * jwsHeader.x5c,
296
+ * namespaceCertificates
297
+ * );
298
+ * console.log('Chain validates to trusted root', result.validationResult.warnings);
299
+ * } catch (error) {
300
+ * console.error('Validation failed:', error.message);
301
+ * }
302
+ * ```
303
+ */
304
+ export async function validateJWSCertificateChain(x5c, trustedRootCertificates) {
305
+ const warnings = [];
306
+ try {
307
+ // Validate inputs
308
+ if (!Array.isArray(x5c) || x5c.length === 0) {
309
+ throw new Error('No certificates provided in x5c array');
310
+ }
311
+ if (x5c.length > MAX_CERTS) {
312
+ throw new Error(`Too many certificates in x5c (max ${MAX_CERTS})`);
313
+ }
314
+ if (!Array.isArray(trustedRootCertificates) || trustedRootCertificates.length === 0) {
315
+ throw new Error('No trusted root certificates provided');
316
+ }
317
+ // Parse chain certs (base64 DER)
318
+ const chainCertificates = [];
319
+ for (let i = 0; i < x5c.length; i++) {
320
+ const certBase64 = x5c[i];
321
+ try {
322
+ const certBuffer = base64ToArrayBuffer(certBase64);
323
+ const asn1 = asn1js.fromBER(certBuffer);
324
+ if (asn1.offset === -1) {
325
+ throw new Error(`Invalid DER encoding for certificate at x5c[${i}]`);
326
+ }
327
+ chainCertificates.push(new pkijs.Certificate({ schema: asn1.result }));
328
+ }
329
+ catch (err) {
330
+ const msg = err instanceof Error ? err.message : 'Unknown error';
331
+ throw new Error(`Failed to parse certificate at x5c[${i}]: ${msg}`);
332
+ }
333
+ }
334
+ // Parse trusted roots (PEM)
335
+ const trustedCerts = [];
336
+ for (let i = 0; i < trustedRootCertificates.length; i++) {
337
+ const rootCert = trustedRootCertificates[i];
338
+ try {
339
+ const pem = rootCert.pem;
340
+ if (!pem || pem.trim().length === 0) {
341
+ warnings.push(`Trusted root at index ${i} has no PEM data; skipping`);
342
+ continue;
343
+ }
344
+ const certBuffer = pemToArrayBuffer(pem);
345
+ const asn1 = asn1js.fromBER(certBuffer);
346
+ if (asn1.offset === -1) {
347
+ warnings.push(`Trusted root at index ${i} has invalid DER; skipping`);
348
+ continue;
349
+ }
350
+ trustedCerts.push(new pkijs.Certificate({ schema: asn1.result }));
351
+ }
352
+ catch (err) {
353
+ const msg = err instanceof Error ? err.message : 'Unknown error';
354
+ warnings.push(`Failed to parse trusted root at index ${i}: ${msg}`);
355
+ }
356
+ }
357
+ if (trustedCerts.length === 0) {
358
+ throw new Error('No valid trusted root certificates could be parsed');
359
+ }
360
+ // Build and verify certificate chain using PKI.js
361
+ const chainEngine = new pkijs.CertificateChainValidationEngine({
362
+ trustedCerts,
363
+ certs: chainCertificates,
364
+ checkDate: new Date(),
365
+ });
366
+ const verificationResult = await chainEngine.verify();
367
+ if (!verificationResult.result) {
368
+ // Compose detailed message
369
+ const leaf = chainCertificates[0];
370
+ const leafSubject = getNameStringSafe(leaf.subject);
371
+ const leafIssuer = getNameStringSafe(leaf.issuer);
372
+ const baseMsg = verificationResult.resultMessage || 'Certificate chain validation failed';
373
+ throw new Error(`${baseMsg} (leaf subject='${leafSubject}', issuer='${leafIssuer}')`);
374
+ }
375
+ return {
376
+ valid: true,
377
+ validationResult: {
378
+ warnings,
379
+ errors: [],
380
+ },
381
+ };
382
+ }
383
+ catch (error) {
384
+ const msg = error instanceof Error ? error.message : 'Unknown error';
385
+ const warnSuffix = warnings.length ? `; warnings: ${warnings.join(' | ')}` : '';
386
+ throw new Error(`Validation error: ${msg}${warnSuffix}`);
387
+ }
35
388
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@virtru/dsp-sdk",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "main": "dist/src/index.js",
6
6
  "exports": {
@@ -25,7 +25,7 @@
25
25
  "jsdom": "^22.1.0",
26
26
  "msw": "^2.8.4",
27
27
  "playwright": "^1.52.0",
28
- "vite": "^4.5.14",
28
+ "vite": "^5.4.21",
29
29
  "vite-plugin-dts": "^4.5.4",
30
30
  "vitest": "~3.1.3",
31
31
  "typescript": "5.8.2"
@@ -35,7 +35,9 @@
35
35
  "@connectrpc/connect": "~2.0.2",
36
36
  "@connectrpc/connect-web": "~2.0.2",
37
37
  "@opentdf/sdk": "0.8.0-rc.73",
38
- "@rushstack/heft": "^0.50.0"
38
+ "@rushstack/heft": "^0.50.0",
39
+ "asn1js": "^3.0.5",
40
+ "pkijs": "^3.0.19"
39
41
  },
40
42
  "scripts": {
41
43
  "build": "heft build --clean",
@@ -0,0 +1,179 @@
1
+ // @generated by protoc-gen-es v2.3.0 with parameter "target=ts"
2
+ // @generated from file virtru/common/common.proto (package virtru.common, syntax proto3)
3
+ /* eslint-disable */
4
+
5
+ import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv1";
6
+ import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv1";
7
+ import { file_buf_validate_validate } from "../../buf/validate/validate_pb";
8
+ import type { Timestamp } from "@bufbuild/protobuf/wkt";
9
+ import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
10
+ import type { Message } from "@bufbuild/protobuf";
11
+
12
+ /**
13
+ * Describes the file virtru/common/common.proto.
14
+ */
15
+ export const file_virtru_common_common: GenFile = /*@__PURE__*/
16
+ fileDesc("Chp2aXJ0cnUvY29tbW9uL2NvbW1vbi5wcm90bxINdmlydHJ1LmNvbW1vbiLOAQoITWV0YWRhdGESLgoKY3JlYXRlZF9hdBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASMwoGbGFiZWxzGAMgAygLMiMudmlydHJ1LmNvbW1vbi5NZXRhZGF0YS5MYWJlbHNFbnRyeRotCgtMYWJlbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBInwKD01ldGFkYXRhTXV0YWJsZRI6CgZsYWJlbHMYAyADKAsyKi52aXJ0cnUuY29tbW9uLk1ldGFkYXRhTXV0YWJsZS5MYWJlbHNFbnRyeRotCgtMYWJlbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIlkKD0lkRnFuSWRlbnRpZmllchIWCgJpZBgBIAEoCUIIukgFcgOwAQFIABIZCgNmcW4YAiABKAlCCrpIB3IFEAGIAQFIAEITCgppZGVudGlmaWVyEgW6SAIIASIsCgtQYWdlUmVxdWVzdBINCgVsaW1pdBgBIAEoBRIOCgZvZmZzZXQYAiABKAUiSgoMUGFnZVJlc3BvbnNlEhYKDmN1cnJlbnRfb2Zmc2V0GAEgASgFEhMKC25leHRfb2Zmc2V0GAIgASgFEg0KBXRvdGFsGAMgASgFKn0KEk1ldGFkYXRhVXBkYXRlRW51bRIkCiBNRVRBREFUQV9VUERBVEVfRU5VTV9VTlNQRUNJRklFRBAAEh8KG01FVEFEQVRBX1VQREFURV9FTlVNX0VYVEVORBABEiAKHE1FVEFEQVRBX1VQREFURV9FTlVNX1JFUExBQ0UQAkJ1ChFjb20udmlydHJ1LmNvbW1vbkILQ29tbW9uUHJvdG9QAaICA1ZDWKoCDVZpcnRydS5Db21tb27KAg1WaXJ0cnVcQ29tbW9u4gIZVmlydHJ1XENvbW1vblxHUEJNZXRhZGF0YeoCDlZpcnRydTo6Q29tbW9uYgZwcm90bzM", [file_buf_validate_validate, file_google_protobuf_timestamp]);
17
+
18
+ /**
19
+ * @generated from message virtru.common.Metadata
20
+ */
21
+ export type Metadata = Message<"virtru.common.Metadata"> & {
22
+ /**
23
+ * @generated from field: google.protobuf.Timestamp created_at = 1;
24
+ */
25
+ createdAt?: Timestamp;
26
+
27
+ /**
28
+ * @generated from field: google.protobuf.Timestamp updated_at = 2;
29
+ */
30
+ updatedAt?: Timestamp;
31
+
32
+ /**
33
+ * @generated from field: map<string, string> labels = 3;
34
+ */
35
+ labels: { [key: string]: string };
36
+ };
37
+
38
+ /**
39
+ * Describes the message virtru.common.Metadata.
40
+ * Use `create(MetadataSchema)` to create a new message.
41
+ */
42
+ export const MetadataSchema: GenMessage<Metadata> = /*@__PURE__*/
43
+ messageDesc(file_virtru_common_common, 0);
44
+
45
+ /**
46
+ * @generated from message virtru.common.MetadataMutable
47
+ */
48
+ export type MetadataMutable = Message<"virtru.common.MetadataMutable"> & {
49
+ /**
50
+ * @generated from field: map<string, string> labels = 3;
51
+ */
52
+ labels: { [key: string]: string };
53
+ };
54
+
55
+ /**
56
+ * Describes the message virtru.common.MetadataMutable.
57
+ * Use `create(MetadataMutableSchema)` to create a new message.
58
+ */
59
+ export const MetadataMutableSchema: GenMessage<MetadataMutable> = /*@__PURE__*/
60
+ messageDesc(file_virtru_common_common, 1);
61
+
62
+ /**
63
+ * @generated from message virtru.common.IdFqnIdentifier
64
+ */
65
+ export type IdFqnIdentifier = Message<"virtru.common.IdFqnIdentifier"> & {
66
+ /**
67
+ * @generated from oneof virtru.common.IdFqnIdentifier.identifier
68
+ */
69
+ identifier: {
70
+ /**
71
+ * @generated from field: string id = 1;
72
+ */
73
+ value: string;
74
+ case: "id";
75
+ } | {
76
+ /**
77
+ * @generated from field: string fqn = 2;
78
+ */
79
+ value: string;
80
+ case: "fqn";
81
+ } | { case: undefined; value?: undefined };
82
+ };
83
+
84
+ /**
85
+ * Describes the message virtru.common.IdFqnIdentifier.
86
+ * Use `create(IdFqnIdentifierSchema)` to create a new message.
87
+ */
88
+ export const IdFqnIdentifierSchema: GenMessage<IdFqnIdentifier> = /*@__PURE__*/
89
+ messageDesc(file_virtru_common_common, 2);
90
+
91
+ /**
92
+ * @generated from message virtru.common.PageRequest
93
+ */
94
+ export type PageRequest = Message<"virtru.common.PageRequest"> & {
95
+ /**
96
+ * Optional
97
+ * Set to configured default limit if not provided
98
+ * Maximum limit set in platform config and enforced by services
99
+ *
100
+ * @generated from field: int32 limit = 1;
101
+ */
102
+ limit: number;
103
+
104
+ /**
105
+ * Optional
106
+ * Defaulted if not provided
107
+ *
108
+ * @generated from field: int32 offset = 2;
109
+ */
110
+ offset: number;
111
+ };
112
+
113
+ /**
114
+ * Describes the message virtru.common.PageRequest.
115
+ * Use `create(PageRequestSchema)` to create a new message.
116
+ */
117
+ export const PageRequestSchema: GenMessage<PageRequest> = /*@__PURE__*/
118
+ messageDesc(file_virtru_common_common, 3);
119
+
120
+ /**
121
+ * @generated from message virtru.common.PageResponse
122
+ */
123
+ export type PageResponse = Message<"virtru.common.PageResponse"> & {
124
+ /**
125
+ * Requested pagination offset
126
+ *
127
+ * @generated from field: int32 current_offset = 1;
128
+ */
129
+ currentOffset: number;
130
+
131
+ /**
132
+ * Calculated with request limit + offset or defaults
133
+ * Empty when none remain after current page
134
+ *
135
+ * @generated from field: int32 next_offset = 2;
136
+ */
137
+ nextOffset: number;
138
+
139
+ /**
140
+ * Total count of entire list
141
+ *
142
+ * @generated from field: int32 total = 3;
143
+ */
144
+ total: number;
145
+ };
146
+
147
+ /**
148
+ * Describes the message virtru.common.PageResponse.
149
+ * Use `create(PageResponseSchema)` to create a new message.
150
+ */
151
+ export const PageResponseSchema: GenMessage<PageResponse> = /*@__PURE__*/
152
+ messageDesc(file_virtru_common_common, 4);
153
+
154
+ /**
155
+ * @generated from enum virtru.common.MetadataUpdateEnum
156
+ */
157
+ export enum MetadataUpdateEnum {
158
+ /**
159
+ * @generated from enum value: METADATA_UPDATE_ENUM_UNSPECIFIED = 0;
160
+ */
161
+ UNSPECIFIED = 0,
162
+
163
+ /**
164
+ * @generated from enum value: METADATA_UPDATE_ENUM_EXTEND = 1;
165
+ */
166
+ EXTEND = 1,
167
+
168
+ /**
169
+ * @generated from enum value: METADATA_UPDATE_ENUM_REPLACE = 2;
170
+ */
171
+ REPLACE = 2,
172
+ }
173
+
174
+ /**
175
+ * Describes the enum virtru.common.MetadataUpdateEnum.
176
+ */
177
+ export const MetadataUpdateEnumSchema: GenEnum<MetadataUpdateEnum> = /*@__PURE__*/
178
+ enumDesc(file_virtru_common_common, 0);
179
+
@@ -0,0 +1,44 @@
1
+ // @generated by protoc-gen-connect-es v1.6.1 with parameter "target=ts"
2
+ // @generated from file virtru/policy/certificates/v1/certificates.proto (package virtru.policy.certificates.v1, syntax proto3)
3
+ /* eslint-disable */
4
+ // @ts-nocheck
5
+
6
+ import { AssignCertificateToNamespaceRequest, AssignCertificateToNamespaceResponse, ListCertificatesByNamespaceRequest, ListCertificatesByNamespaceResponse, RemoveCertificateFromNamespaceRequest, RemoveCertificateFromNamespaceResponse } from "./certificates_pb.js";
7
+ import { MethodKind } from "@bufbuild/protobuf";
8
+
9
+ /**
10
+ * @generated from service virtru.policy.certificates.v1.CertificateService
11
+ */
12
+ export const CertificateService = {
13
+ typeName: "virtru.policy.certificates.v1.CertificateService",
14
+ methods: {
15
+ /**
16
+ * @generated from rpc virtru.policy.certificates.v1.CertificateService.ListCertificatesByNamespace
17
+ */
18
+ listCertificatesByNamespace: {
19
+ name: "ListCertificatesByNamespace",
20
+ I: ListCertificatesByNamespaceRequest,
21
+ O: ListCertificatesByNamespaceResponse,
22
+ kind: MethodKind.Unary,
23
+ },
24
+ /**
25
+ * @generated from rpc virtru.policy.certificates.v1.CertificateService.AssignCertificateToNamespace
26
+ */
27
+ assignCertificateToNamespace: {
28
+ name: "AssignCertificateToNamespace",
29
+ I: AssignCertificateToNamespaceRequest,
30
+ O: AssignCertificateToNamespaceResponse,
31
+ kind: MethodKind.Unary,
32
+ },
33
+ /**
34
+ * @generated from rpc virtru.policy.certificates.v1.CertificateService.RemoveCertificateFromNamespace
35
+ */
36
+ removeCertificateFromNamespace: {
37
+ name: "RemoveCertificateFromNamespace",
38
+ I: RemoveCertificateFromNamespaceRequest,
39
+ O: RemoveCertificateFromNamespaceResponse,
40
+ kind: MethodKind.Unary,
41
+ },
42
+ }
43
+ } as const;
44
+