@lifesi/genesis 0.1.1 → 0.1.3

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 (44) hide show
  1. package/dist/beacons.d.ts +46 -0
  2. package/dist/beacons.js +20 -0
  3. package/dist/client.d.ts +7669 -1635
  4. package/dist/client.js +54 -5
  5. package/dist/dials.d.ts +171 -1
  6. package/dist/dials.js +40 -0
  7. package/dist/fleets.d.ts +109 -1
  8. package/dist/fleets.js +89 -1
  9. package/dist/flocks.d.ts +73 -0
  10. package/dist/flocks.js +22 -0
  11. package/dist/generated/operations.d.ts +7669 -1635
  12. package/dist/generated/operations.js +9193 -1691
  13. package/dist/generated/schema.d.ts +16979 -5698
  14. package/dist/genesis.d.ts +795 -13
  15. package/dist/genesis.js +21 -0
  16. package/dist/genesis.openapi.json +23483 -7599
  17. package/dist/henry.d.ts +7 -0
  18. package/dist/henry.js +23 -0
  19. package/dist/hives-cells.d.ts +127 -0
  20. package/dist/hives-cells.js +151 -0
  21. package/dist/hives-environment.d.ts +28 -0
  22. package/dist/hives-environment.js +58 -0
  23. package/dist/hives-functions.d.ts +1 -1
  24. package/dist/hives-functions.js +3 -1
  25. package/dist/hives-marketplace.d.ts +128 -0
  26. package/dist/hives-marketplace.js +187 -0
  27. package/dist/hives-node.js +2 -0
  28. package/dist/hives-operations.d.ts +304 -0
  29. package/dist/hives-operations.js +39 -0
  30. package/dist/hives-queues.d.ts +121 -0
  31. package/dist/hives-queues.js +106 -0
  32. package/dist/hives-resources-transport.d.ts +18 -0
  33. package/dist/hives-resources-transport.js +165 -0
  34. package/dist/hives-runtimes.d.ts +34 -0
  35. package/dist/hives-runtimes.js +32 -0
  36. package/dist/hives-volumes.d.ts +64 -0
  37. package/dist/hives-volumes.js +117 -0
  38. package/dist/index.d.ts +8 -1
  39. package/dist/index.js +3 -0
  40. package/dist/runner-grant.d.ts +10 -0
  41. package/dist/runner-grant.js +133 -0
  42. package/dist/runner.d.ts +16 -0
  43. package/dist/runner.js +4 -0
  44. package/package.json +6 -1
package/dist/henry.d.ts CHANGED
@@ -14,6 +14,13 @@ export declare function henryModule(client: GenesisClient): {
14
14
  id: string;
15
15
  }[];
16
16
  }>;
17
+ receipts: {
18
+ /** Current standalone Henry public signer. Pin through trusted deployment custody before verifying a receipt. */
19
+ verificationKey: () => Promise<{
20
+ keyId: string;
21
+ publicKeyBase64: string;
22
+ }>;
23
+ };
17
24
  runs: {
18
25
  list: (page_token?: string) => Promise<{
19
26
  runs: import("./index.js").components["schemas"]["Henry.Run"][];
package/dist/henry.js CHANGED
@@ -1,8 +1,31 @@
1
+ function receiptVerificationKey(value) {
2
+ if (!value || typeof value !== 'object' || Array.isArray(value))
3
+ throw new Error('Henry returned an invalid receipt verification key.');
4
+ const key = value;
5
+ if (Object.keys(key).length !== 2 || !Object.hasOwn(key, 'keyId') || !Object.hasOwn(key, 'publicKeyBase64')
6
+ || typeof key.keyId !== 'string' || !key.keyId.trim() || key.keyId.length > 256 || /[\x00-\x1f\x7f]/.test(key.keyId)
7
+ || typeof key.publicKeyBase64 !== 'string' || key.publicKeyBase64.length !== 44
8
+ || !/^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(key.publicKeyBase64)) {
9
+ throw new Error('Henry returned an invalid receipt verification key.');
10
+ }
11
+ return { keyId: key.keyId, publicKeyBase64: key.publicKeyBase64 };
12
+ }
1
13
  /** Henry always derives its organization from the gateway's verified caller. */
2
14
  export function henryModule(client) {
3
15
  return {
4
16
  config: () => client.request('henry_getConfig'),
5
17
  credential: (api_key) => client.request('henry_putCredential', { body: { api_key } }),
18
+ receipts: {
19
+ /** Current standalone Henry public signer. Pin through trusted deployment custody before verifying a receipt. */
20
+ verificationKey: async () => {
21
+ try {
22
+ return receiptVerificationKey(await client.request('henry_getReceiptVerificationKey'));
23
+ }
24
+ catch {
25
+ throw new Error('Henry returned an invalid receipt verification key.');
26
+ }
27
+ },
28
+ },
6
29
  runs: {
7
30
  list: (page_token) => client.request('henry_listRuns', page_token ? { page_token } : {}),
8
31
  create: (body) => client.request('henry_createRun', { body: { ...body, run_id: body.run_id ?? globalThis.crypto.randomUUID() } }),
@@ -0,0 +1,127 @@
1
+ import type { GenesisClient } from './client.js';
2
+ import { type HivesResourceOptions } from './hives-resources-transport.js';
3
+ export interface HivesCorsRule {
4
+ allowed_origins: string[];
5
+ allowed_methods: string[];
6
+ allowed_headers: string[];
7
+ exposed_headers: string[];
8
+ max_age_secs: number;
9
+ }
10
+ export interface HivesBucket {
11
+ id: string;
12
+ tenant_id: string;
13
+ project_id: string;
14
+ name: string;
15
+ region: string;
16
+ visibility: string;
17
+ status: string;
18
+ object_count: number | null;
19
+ size_bytes: number | null;
20
+ statistics_scope: 'unmeasured_provider_inventory' | 'retained_legacy_metadata';
21
+ created_at: string;
22
+ provider_binding: {
23
+ provider: 'gcs';
24
+ region: string;
25
+ state: string;
26
+ requires_reconciliation: boolean;
27
+ } | null;
28
+ operation_state: string | null;
29
+ }
30
+ export interface HivesObject {
31
+ key: string;
32
+ bucket_id: string;
33
+ size_bytes: number;
34
+ etag: string;
35
+ last_modified: string;
36
+ generation: string;
37
+ content_type: string | null;
38
+ metadata: Record<string, string> | null;
39
+ metadata_scope: string;
40
+ }
41
+ export interface HivesObjectAcknowledgement {
42
+ bucket_id: string;
43
+ key: string;
44
+ size_bytes: number;
45
+ etag: string;
46
+ generation: string;
47
+ content_type: string | null;
48
+ }
49
+ export interface HivesObjectList {
50
+ objects: HivesObject[];
51
+ common_prefixes: string[];
52
+ is_truncated: boolean;
53
+ next_continuation_token: string | null;
54
+ total: number | null;
55
+ }
56
+ export interface HivesBucketList {
57
+ data: HivesBucket[];
58
+ pagination: {
59
+ page: number;
60
+ per_page: number;
61
+ total: number;
62
+ total_pages: number;
63
+ has_next: boolean;
64
+ has_prev: boolean;
65
+ };
66
+ }
67
+ export interface HivesCreateBucket {
68
+ name: string;
69
+ region?: 'us-central1';
70
+ visibility?: 'private' | 'publicread';
71
+ cors_rules?: HivesCorsRule[];
72
+ }
73
+ export interface HivesPresign {
74
+ key: string;
75
+ method?: 'GET' | 'PUT';
76
+ expires_in_secs?: number;
77
+ content_type?: string;
78
+ content_length?: number;
79
+ }
80
+ export interface HivesPresignedUrl {
81
+ url: string;
82
+ expires_at: string;
83
+ method: 'GET' | 'PUT';
84
+ required_headers?: Record<string, string>;
85
+ }
86
+ export declare function hivesObjectKey(key: string): string;
87
+ export declare function hivesCells(client: GenesisClient): {
88
+ list(project: string, query?: {
89
+ page?: number;
90
+ per_page?: number;
91
+ }, options?: HivesResourceOptions): Promise<HivesBucketList>;
92
+ get(project: string, id: string, options?: HivesResourceOptions): Promise<HivesBucket>;
93
+ /** A pending provider_binding is an uncertain outcome, never a completed-create claim. */
94
+ create(project: string, body: HivesCreateBucket, options?: HivesResourceOptions): Promise<HivesBucket>;
95
+ remove(project: string, id: string, options?: HivesResourceOptions): Promise<{
96
+ id: string;
97
+ success: boolean;
98
+ message: string;
99
+ }>;
100
+ reconcile(project: string, id: string, options?: HivesResourceOptions): Promise<{
101
+ bucket: HivesBucket;
102
+ outcome: string;
103
+ }>;
104
+ cors: {
105
+ get: (project: string, id: string, options?: HivesResourceOptions) => Promise<HivesCorsRule[]>;
106
+ set: (project: string, id: string, rules: HivesCorsRule[], options?: HivesResourceOptions) => Promise<HivesCorsRule[]>;
107
+ };
108
+ objects: {
109
+ list(project: string, id: string, query?: {
110
+ prefix?: string;
111
+ delimiter?: string;
112
+ continuation_token?: string;
113
+ max_keys?: number;
114
+ }, options?: HivesResourceOptions): Promise<HivesObjectList>;
115
+ put(project: string, id: string, key: string, bytes: Blob | ArrayBuffer | ArrayBufferView, options?: HivesResourceOptions & {
116
+ content_type?: string;
117
+ }): Promise<HivesObjectAcknowledgement>;
118
+ remove: (project: string, id: string, key: string, options?: HivesResourceOptions) => Promise<void>;
119
+ download: (project: string, id: string, key: string, options?: HivesResourceOptions) => Promise<Response>;
120
+ /** Existing flat-key path compatibility; nested keys use canonical collection methods above. */
121
+ putFlat(project: string, id: string, key: string, bytes: Blob | ArrayBuffer | ArrayBufferView, options?: HivesResourceOptions & {
122
+ content_type?: string;
123
+ }): Promise<HivesObjectAcknowledgement>;
124
+ removeFlat: (project: string, id: string, key: string, options?: HivesResourceOptions) => Promise<void>;
125
+ };
126
+ presign(project: string, id: string, body: HivesPresign, options?: HivesResourceOptions): Promise<HivesPresignedUrl>;
127
+ };
@@ -0,0 +1,151 @@
1
+ import { HIVES_OBJECT_BYTES, hivesResourceCall, hivesResourceId, hivesObjectBody, hivesContentType, resourceError } from './hives-resources-transport.js';
2
+ export function hivesObjectKey(key) {
3
+ const bytes = new TextEncoder().encode(key);
4
+ if (typeof key !== 'string' || !key || bytes.length > 1024 || new TextDecoder('utf-8', { fatal: true }).decode(bytes) !== key
5
+ || key.startsWith('/') || key.endsWith('/') || /[\u0000-\u001f\u007f-\u009f\\]/.test(key) || key.split('/').some(p => !p || p === '.' || p === '..'))
6
+ throw resourceError(0);
7
+ let binary = '';
8
+ for (const byte of bytes)
9
+ binary += String.fromCharCode(byte);
10
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
11
+ }
12
+ function cors(rules) {
13
+ if (!Array.isArray(rules) || rules.length > 100)
14
+ throw resourceError(0);
15
+ return rules.map(rule => {
16
+ if (!rule || typeof rule !== 'object' || Object.keys(rule).some(k => !['allowed_origins', 'allowed_methods', 'allowed_headers', 'exposed_headers', 'max_age_secs'].includes(k))
17
+ || !Array.isArray(rule.allowed_origins) || !rule.allowed_origins.length || rule.allowed_origins.length > 100
18
+ || !Array.isArray(rule.allowed_methods) || !rule.allowed_methods.length || rule.allowed_methods.length > 6
19
+ || !Array.isArray(rule.allowed_headers) || rule.allowed_headers.length !== 1 || rule.allowed_headers[0] !== '*'
20
+ || !Array.isArray(rule.exposed_headers) || rule.exposed_headers.length > 100
21
+ || !Number.isInteger(rule.max_age_secs) || rule.max_age_secs < 0 || rule.max_age_secs > 86400)
22
+ throw resourceError(0);
23
+ for (const origin of rule.allowed_origins) {
24
+ if (origin === '*')
25
+ continue;
26
+ if (typeof origin !== 'string')
27
+ throw resourceError(0);
28
+ let url;
29
+ try {
30
+ url = new URL(origin);
31
+ }
32
+ catch {
33
+ throw resourceError(0);
34
+ }
35
+ if (!['http:', 'https:'].includes(url.protocol) || !url.hostname || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
36
+ throw resourceError(0);
37
+ }
38
+ if (rule.allowed_methods.some(m => !['GET', 'HEAD', 'PUT', 'POST', 'DELETE'].includes(m))
39
+ || rule.exposed_headers.some(h => typeof h !== 'string' || h.length > 256 || !/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(h)))
40
+ throw resourceError(0);
41
+ return { allowed_origins: [...rule.allowed_origins], allowed_methods: [...rule.allowed_methods], allowed_headers: ['*'], exposed_headers: [...rule.exposed_headers], max_age_secs: rule.max_age_secs };
42
+ });
43
+ }
44
+ function bucket(value, project, id) {
45
+ if (!value || typeof value !== 'object' || value.project_id !== project || typeof value.id !== 'string' || id !== undefined && value.id !== id
46
+ || !['unmeasured_provider_inventory', 'retained_legacy_metadata'].includes(value.statistics_scope)
47
+ || [value.object_count, value.size_bytes].some(v => v !== null && (!Number.isSafeInteger(v) || v < 0))
48
+ || (value.statistics_scope === 'unmeasured_provider_inventory' && (value.object_count !== null || value.size_bytes !== null)))
49
+ throw resourceError(0);
50
+ if (value.statistics_scope === 'unmeasured_provider_inventory' && !value.provider_binding)
51
+ throw resourceError(0);
52
+ if (value.provider_binding !== null && (!value.provider_binding || value.provider_binding.provider !== 'gcs' || typeof value.provider_binding.state !== 'string' || typeof value.provider_binding.requires_reconciliation !== 'boolean'))
53
+ throw resourceError(0);
54
+ return Object.fromEntries(['id', 'tenant_id', 'project_id', 'name', 'region', 'visibility', 'status', 'object_count', 'size_bytes', 'statistics_scope', 'created_at', 'provider_binding', 'operation_state'].map(k => [k, value[k]]));
55
+ }
56
+ function object(value, id) {
57
+ if (!value || value.bucket_id !== id || typeof value.key !== 'string' || !Number.isSafeInteger(value.size_bytes) || value.size_bytes < 0 || typeof value.generation !== 'string')
58
+ throw resourceError(0);
59
+ hivesObjectKey(value.key);
60
+ return Object.fromEntries(['key', 'bucket_id', 'size_bytes', 'etag', 'last_modified', 'generation', 'content_type', 'metadata', 'metadata_scope'].map(k => [k, value[k]]));
61
+ }
62
+ function acknowledgement(value, key, id, size) {
63
+ if (!value || value.bucket_id !== id || value.key !== key || value.size_bytes !== size || !Number.isSafeInteger(value.size_bytes) || value.size_bytes < 0 || typeof value.etag !== 'string' || typeof value.generation !== 'string' || value.content_type !== null && typeof value.content_type !== 'string')
64
+ throw resourceError(0);
65
+ return { key: value.key, bucket_id: value.bucket_id, size_bytes: value.size_bytes, etag: value.etag, generation: value.generation, content_type: value.content_type };
66
+ }
67
+ export function hivesCells(client) {
68
+ const ids = (project_id, bucket_id) => ({ project_id: hivesResourceId(project_id), ...(bucket_id === undefined ? {} : { bucket_id: hivesResourceId(bucket_id) }) });
69
+ const call = (id, input, options, mode = 'json', limit = 2 * 1024 * 1024) => hivesResourceCall(client, id, input, options, mode, limit, 100_000);
70
+ return {
71
+ async list(project, query = {}, options) {
72
+ if (Object.keys(query).some(k => !['page', 'per_page'].includes(k)) || query.page !== undefined && (!Number.isInteger(query.page) || query.page < 1 || query.page > 10000) || query.per_page !== undefined && (!Number.isInteger(query.per_page) || query.per_page < 1 || query.per_page > 100))
73
+ throw resourceError(0);
74
+ const result = await call('hives_list_buckets', { ...query, ...ids(project) }, options);
75
+ if (!result || !Array.isArray(result.data) || !result.pagination)
76
+ throw resourceError(0);
77
+ return { ...result, data: result.data.map(row => bucket(row, project)) };
78
+ },
79
+ async get(project, id, options) { return bucket(await call('hives_get_bucket', ids(project, id), options), project, id); },
80
+ /** A pending provider_binding is an uncertain outcome, never a completed-create claim. */
81
+ async create(project, body, options) {
82
+ if (!body || typeof body.name !== 'string' || !/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(body.name) || body.region !== undefined && body.region !== 'us-central1'
83
+ || body.visibility !== undefined && !['private', 'publicread'].includes(body.visibility) || Object.keys(body).some(k => !['name', 'region', 'visibility', 'cors_rules'].includes(k)))
84
+ throw resourceError(0);
85
+ const checked = { ...body, ...(body.cors_rules === undefined ? {} : { cors_rules: cors(body.cors_rules) }) };
86
+ return bucket(await call('hives_create_bucket', { ...ids(project), body: checked }, options), project);
87
+ },
88
+ async remove(project, id, options) {
89
+ const result = await call('hives_delete_bucket', ids(project, id), options);
90
+ if (!result || result.id !== id || result.success !== true)
91
+ throw resourceError(0);
92
+ return result;
93
+ },
94
+ async reconcile(project, id, options) {
95
+ const result = await call('hives_reconcile', ids(project, id), options);
96
+ if (!result || typeof result.outcome !== 'string' || result.bucket?.id !== id)
97
+ throw resourceError(0);
98
+ return { ...result, bucket: bucket(result.bucket, project) };
99
+ },
100
+ cors: {
101
+ get: async (project, id, options) => cors(await call('hives_get_cors_config', ids(project, id), options)),
102
+ set: async (project, id, rules, options) => cors(await call('hives_set_cors_config', { ...ids(project, id), body: { rules: cors(rules) } }, options)),
103
+ },
104
+ objects: {
105
+ async list(project, id, query = {}, options) {
106
+ if (query.max_keys !== undefined && (!Number.isInteger(query.max_keys) || query.max_keys < 1 || query.max_keys > 1000))
107
+ throw resourceError(0);
108
+ const result = await call('hives_list_objects', { ...query, ...ids(project, id) }, options);
109
+ if (!result || !Array.isArray(result.objects) || !Array.isArray(result.common_prefixes) || typeof result.is_truncated !== 'boolean' || result.total !== null)
110
+ throw resourceError(0);
111
+ return { ...result, objects: result.objects.map(row => object(row, id)) };
112
+ },
113
+ async put(project, id, key, bytes, options = {}) {
114
+ const body = await hivesObjectBody(bytes);
115
+ const content_type = hivesContentType(options.content_type);
116
+ return acknowledgement(await call('hives_upload_object_by_key', { ...ids(project, id), key_base64url: hivesObjectKey(key), body, content_type }, options), key, id, body.byteLength);
117
+ },
118
+ remove: (project, id, key, options) => call('hives_delete_object_by_key', { ...ids(project, id), key_base64url: hivesObjectKey(key) }, options, 'empty'),
119
+ download: (project, id, key, options) => call('hives_download_object_by_key', { ...ids(project, id), key_base64url: hivesObjectKey(key) }, options, 'binary', HIVES_OBJECT_BYTES),
120
+ /** Existing flat-key path compatibility; nested keys use canonical collection methods above. */
121
+ async putFlat(project, id, key, bytes, options = {}) {
122
+ hivesObjectKey(key);
123
+ if (!/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*$/.test(key))
124
+ throw resourceError(0);
125
+ const body = await hivesObjectBody(bytes);
126
+ return acknowledgement(await call('hives_upload_object', { ...ids(project, id), key, body, content_type: hivesContentType(options.content_type) }, options), key, id, body.byteLength);
127
+ },
128
+ removeFlat: (project, id, key, options) => { hivesObjectKey(key); if (!/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*$/.test(key))
129
+ throw resourceError(0); return call('hives_delete_object', { ...ids(project, id), key }, options, 'empty'); },
130
+ },
131
+ async presign(project, id, body, options) {
132
+ hivesObjectKey(body.key);
133
+ const method = body.method ?? 'GET';
134
+ if (!['GET', 'PUT'].includes(method) || body.expires_in_secs !== undefined && (!Number.isInteger(body.expires_in_secs) || body.expires_in_secs < 60 || body.expires_in_secs > 900)
135
+ || method === 'PUT' && (body.content_length === undefined || !Number.isInteger(body.content_length) || body.content_length < 0 || body.content_length > HIVES_OBJECT_BYTES))
136
+ throw resourceError(0);
137
+ if (body.content_type !== undefined)
138
+ hivesContentType(body.content_type);
139
+ const result = await call('hives_generate_presigned_url', { ...ids(project, id), body }, options);
140
+ if (!result || typeof result.url !== 'string' || result.method !== method || typeof result.expires_at !== 'string')
141
+ throw resourceError(0);
142
+ const url = new URL(result.url);
143
+ if (url.protocol !== 'https:' || url.hostname !== 'storage.googleapis.com' || url.username || url.password || url.hash)
144
+ throw resourceError(0);
145
+ const headers = result.required_headers;
146
+ if (headers !== undefined && (!headers || typeof headers !== 'object' || Array.isArray(headers) || Object.entries(headers).some(([k, v]) => !['content-type', 'content-length', 'x-goog-if-generation-match'].includes(k.toLowerCase()) || typeof v !== 'string' || /[\u0000-\u001f\u007f]/.test(v))))
147
+ throw resourceError(0);
148
+ return { url: result.url, expires_at: result.expires_at, method: result.method, ...(headers ? { required_headers: { ...headers } } : {}) };
149
+ },
150
+ };
151
+ }
@@ -0,0 +1,28 @@
1
+ /** Environment metadata never carries stored values. Reveals are explicit. */
2
+ export declare function validateHivesEnvironment(input: unknown): Record<string, string>;
3
+ export declare function hivesEnvironmentMetadata(value: unknown, project: unknown, updated: boolean): {
4
+ project_id: string;
5
+ updated: {
6
+ name: string;
7
+ }[];
8
+ data?: undefined;
9
+ pagination?: undefined;
10
+ } | {
11
+ project_id: string;
12
+ data: {
13
+ name: string;
14
+ }[];
15
+ pagination: {
16
+ page: unknown;
17
+ per_page: unknown;
18
+ total: unknown;
19
+ total_pages: unknown;
20
+ has_next: boolean;
21
+ has_prev: boolean;
22
+ };
23
+ updated?: undefined;
24
+ };
25
+ export declare function hivesEnvironmentReveal(value: unknown, key: unknown): {
26
+ name: string;
27
+ value: string;
28
+ };
@@ -0,0 +1,58 @@
1
+ /** Environment metadata never carries stored values. Reveals are explicit. */
2
+ export function validateHivesEnvironment(input) {
3
+ if (!input || typeof input !== 'object' || Array.isArray(input))
4
+ throw new Error('Environment input must be a flat JSON map of names to string values.');
5
+ const entries = Object.entries(input);
6
+ if (entries.length < 1 || entries.length > 100)
7
+ throw new Error('Environment updates require 1–100 names.');
8
+ const result = Object.create(null);
9
+ for (const [name, value] of entries) {
10
+ if (name.length > 255 || !/^[A-Za-z][A-Za-z0-9_]*$/.test(name))
11
+ throw new Error('Environment names must start with a letter and contain only letters, numbers and underscores (up to 255 characters).');
12
+ if (typeof value !== 'string' || new TextEncoder().encode(value).length > 65536)
13
+ throw new Error('Environment values must be strings of at most 65,536 UTF-8 bytes. Empty values are allowed.');
14
+ result[name] = value;
15
+ }
16
+ if (new TextEncoder().encode(JSON.stringify(result)).length > 2 * 1024 * 1024)
17
+ throw new Error('Environment input exceeds 2 MiB. Split it into smaller batches.');
18
+ return result;
19
+ }
20
+ function record(value) {
21
+ if (!value || typeof value !== 'object' || Array.isArray(value))
22
+ throw new Error('Hives returned invalid environment metadata.');
23
+ return value;
24
+ }
25
+ function names(value) {
26
+ if (!Array.isArray(value))
27
+ throw new Error('Hives returned invalid environment metadata.');
28
+ return value.map((value) => {
29
+ const row = record(value);
30
+ if (typeof row.name !== 'string')
31
+ throw new Error('Hives returned invalid environment metadata.');
32
+ return { name: row.name };
33
+ });
34
+ }
35
+ export function hivesEnvironmentMetadata(value, project, updated) {
36
+ const data = record(value);
37
+ if (typeof project !== 'string' || data.project_id !== project)
38
+ throw new Error('Hives returned environment metadata for a different project.');
39
+ if (updated)
40
+ return { project_id: project, updated: names(data.updated) };
41
+ const pagination = record(data.pagination);
42
+ for (const key of ['page', 'per_page', 'total', 'total_pages']) {
43
+ if (!Number.isSafeInteger(pagination[key]) || pagination[key] < (key === 'page' || key === 'per_page' ? 1 : 0))
44
+ throw new Error('Hives returned invalid environment pagination.');
45
+ }
46
+ if (typeof pagination.has_next !== 'boolean' || typeof pagination.has_prev !== 'boolean')
47
+ throw new Error('Hives returned invalid environment pagination.');
48
+ return { project_id: project, data: names(data.data), pagination: {
49
+ page: pagination.page, per_page: pagination.per_page, total: pagination.total, total_pages: pagination.total_pages,
50
+ has_next: pagination.has_next, has_prev: pagination.has_prev,
51
+ } };
52
+ }
53
+ export function hivesEnvironmentReveal(value, key) {
54
+ const data = record(value);
55
+ if (typeof key !== 'string' || data.name !== key || typeof data.value !== 'string' || new TextEncoder().encode(data.value).length > 65536)
56
+ throw new Error('Hives returned invalid environment reveal data.');
57
+ return { name: data.name, value: data.value };
58
+ }
@@ -12,4 +12,4 @@ export declare function validateHivesInvocation(input: unknown): asserts input i
12
12
  /** Safe display/transport headers; customer headers never establish identity. */
13
13
  export declare function hivesFunctionResponseHeaders(headers: Headers): Headers;
14
14
  /** Metadata contracts cannot accidentally expose an upstream env/ciphertext field. */
15
- export declare function hivesFunctionMetadata(input: unknown, project: unknown): Record<string, unknown>;
15
+ export declare function hivesFunctionMetadata(input: unknown, project: unknown, expectedId?: unknown): Record<string, unknown>;
@@ -84,11 +84,13 @@ export function hivesFunctionResponseHeaders(headers) {
84
84
  return safe;
85
85
  }
86
86
  /** Metadata contracts cannot accidentally expose an upstream env/ciphertext field. */
87
- export function hivesFunctionMetadata(input, project) {
87
+ export function hivesFunctionMetadata(input, project, expectedId) {
88
88
  if (!input || typeof input !== 'object' || input.project_id !== project) {
89
89
  throw new Error('Hives returned invalid or wrong-project function metadata.');
90
90
  }
91
91
  const row = input;
92
+ if (expectedId !== undefined && row.id !== expectedId)
93
+ throw new Error('Hives returned mismatched function metadata.');
92
94
  return Object.fromEntries(['id', 'tenant_id', 'project_id', 'name', 'description', 'handler', 'route', 'memory_mb', 'timeout_ms',
93
95
  'status', 'invocations', 'avg_duration_ms', 'created_at', 'updated_at'].map((key) => [key, row[key]]));
94
96
  }
@@ -0,0 +1,128 @@
1
+ import type { GenesisClient } from './client.js';
2
+ import { type HivesResourceOptions } from './hives-resources-transport.js';
3
+ export interface HivesMarketplacePackage {
4
+ id: string;
5
+ slug: string;
6
+ name: string;
7
+ description: string;
8
+ author_name: string;
9
+ visibility: 'public' | 'private' | 'unlisted';
10
+ categories: string[];
11
+ keywords: string[];
12
+ license: string;
13
+ installs: number;
14
+ stars: number;
15
+ verified: boolean;
16
+ featured: boolean;
17
+ free: boolean;
18
+ latest_version: string;
19
+ version_count: number;
20
+ owned: boolean;
21
+ created_at: string;
22
+ updated_at: string;
23
+ }
24
+ export interface HivesMarketplaceVersion {
25
+ id: string;
26
+ package_id: string;
27
+ version: string;
28
+ module_hash: string;
29
+ size_bytes: number;
30
+ readme: string;
31
+ changelog: string;
32
+ required_env: string[];
33
+ downloads: number;
34
+ deprecated: boolean;
35
+ published_at: string;
36
+ }
37
+ export interface HivesMarketplaceInstallation {
38
+ id: string;
39
+ package_id: string;
40
+ slug: string;
41
+ name: string;
42
+ project_id: string;
43
+ version: string | null;
44
+ deployment_id: string | null;
45
+ deployment_status: string | null;
46
+ pending_version: string | null;
47
+ pending_deployment_id: string | null;
48
+ pending_deployment_status: string | null;
49
+ operation: 'install' | 'update' | 'cleanup' | 'uninstall' | null;
50
+ status: 'active' | 'updating' | 'failed' | 'uninstalled';
51
+ latest_version: string | null;
52
+ installed_at: string;
53
+ }
54
+ export interface HivesMarketplaceCategory {
55
+ id: string;
56
+ slug: string;
57
+ name: string;
58
+ description: string | null;
59
+ icon_url: string | null;
60
+ package_count: number;
61
+ sort_order: number;
62
+ }
63
+ export interface HivesMarketplacePage<T> {
64
+ data: T[];
65
+ pagination: {
66
+ page: number;
67
+ page_size: number;
68
+ total: number;
69
+ total_pages: number;
70
+ has_next: boolean;
71
+ has_prev: boolean;
72
+ };
73
+ }
74
+ export interface HivesMarketplacePublish {
75
+ slug: string;
76
+ name: string;
77
+ module_hash: string;
78
+ version: string;
79
+ description?: string;
80
+ visibility?: HivesMarketplacePackage['visibility'];
81
+ categories?: string[];
82
+ keywords?: string[];
83
+ readme?: string;
84
+ changelog?: string;
85
+ required_env?: string[];
86
+ license?: string;
87
+ }
88
+ export interface HivesMarketplaceInstall {
89
+ version?: string | null;
90
+ env_overrides?: Record<string, string>;
91
+ }
92
+ export interface HivesMarketplaceSearch {
93
+ q?: string | null;
94
+ category?: string | null;
95
+ free_only?: boolean;
96
+ verified_only?: boolean;
97
+ sort?: 'name' | 'installs' | 'stars' | 'created' | 'updated';
98
+ order?: 'asc' | 'desc';
99
+ page?: number;
100
+ page_size?: number;
101
+ }
102
+ export type HivesMarketplaceDetail = HivesMarketplacePackage & {
103
+ versions: HivesMarketplaceVersion[];
104
+ };
105
+ /** Native Marketplace reuses verified project ownership and persisted deployment lifecycle.
106
+ * Writes are sent once. Read/reconcile saved state after an uncertain acknowledgement. */
107
+ export declare function hivesMarketplace(client: GenesisClient): {
108
+ list(project: string, query?: HivesMarketplaceSearch, options?: HivesResourceOptions): Promise<HivesMarketplacePage<HivesMarketplacePackage>>;
109
+ get(project: string, packageSlug: string, query?: {
110
+ version?: string | null;
111
+ }, options?: HivesResourceOptions): Promise<HivesMarketplaceDetail>;
112
+ versions(project: string, packageSlug: string, query?: {
113
+ page?: number;
114
+ page_size?: number;
115
+ }, options?: HivesResourceOptions): Promise<HivesMarketplacePage<HivesMarketplaceVersion>>;
116
+ featured(project: string, options?: HivesResourceOptions): Promise<HivesMarketplacePage<HivesMarketplacePackage>>;
117
+ categories(project: string, options?: HivesResourceOptions): Promise<HivesMarketplaceCategory[]>;
118
+ publish(project: string, input: HivesMarketplacePublish, options?: HivesResourceOptions): Promise<HivesMarketplaceDetail>;
119
+ install(project: string, packageSlug: string, input?: HivesMarketplaceInstall, options?: HivesResourceOptions): Promise<HivesMarketplaceInstallation>;
120
+ update(project: string, packageSlug: string, input?: HivesMarketplaceInstall, options?: HivesResourceOptions): Promise<HivesMarketplaceInstallation>;
121
+ installed(project: string, query?: {
122
+ page?: number;
123
+ page_size?: number;
124
+ }, options?: HivesResourceOptions): Promise<HivesMarketplacePage<HivesMarketplaceInstallation>>;
125
+ getInstallation(project: string, id: string, options?: HivesResourceOptions): Promise<HivesMarketplaceInstallation>;
126
+ reconcile(project: string, id: string, options?: HivesResourceOptions): Promise<HivesMarketplaceInstallation>;
127
+ uninstall(project: string, id: string, options?: HivesResourceOptions): Promise<HivesMarketplaceInstallation>;
128
+ };