@oxyhq/contracts 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/accountGraph.js +58 -0
- package/dist/cjs/index.js +18 -3
- package/dist/cjs/inference/aliaModelRelease.js +20 -8
- package/dist/cjs/inference/modelDocumentation.js +433 -0
- package/dist/cjs/inference/providerConnection.js +77 -7
- package/dist/cjs/inference/version.js +1 -1
- package/dist/cjs/updates.js +2 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/accountGraph.js +58 -0
- package/dist/esm/index.js +6 -1
- package/dist/esm/inference/aliaModelRelease.js +20 -8
- package/dist/esm/inference/modelDocumentation.js +430 -0
- package/dist/esm/inference/providerConnection.js +76 -6
- package/dist/esm/inference/version.js +1 -1
- package/dist/esm/updates.js +2 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/accountGraph.d.ts +62 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/inference/aliaModelRelease.d.ts +20 -8
- package/dist/types/inference/modelDocumentation.d.ts +1603 -0
- package/dist/types/inference/providerConnection.d.ts +33 -4
- package/dist/types/inference/version.d.ts +1 -1
- package/dist/types/updates.d.ts +10 -0
- package/dist/types/userResponse.d.ts +2 -2
- package/package.json +1 -1
package/dist/cjs/accountGraph.js
CHANGED
|
@@ -355,6 +355,64 @@ exports.createAccountRequestSchema = zod_1.z.object({
|
|
|
355
355
|
bio: zod_1.z.string().trim().max(500).optional(),
|
|
356
356
|
avatar: zod_1.z.string().optional(),
|
|
357
357
|
description: zod_1.z.string().trim().max(1000).optional(),
|
|
358
|
+
/**
|
|
359
|
+
* A named color preset KEY (`"blue"`, `"mint"`, …), never a hex value.
|
|
360
|
+
*
|
|
361
|
+
* Here at CREATION for the reason `isPrivateAccount` is, in miniature: for a
|
|
362
|
+
* managed account the color is a visual identity, and an account that is
|
|
363
|
+
* discoverable without one and acquires it on a second request is a face that
|
|
364
|
+
* changes by itself. One statement, one row, born looking like what its owner
|
|
365
|
+
* chose.
|
|
366
|
+
*
|
|
367
|
+
* The VALUE is checked in the API rather than here. The vocabulary is
|
|
368
|
+
* `USER_COLOR_PRESETS`, which is declared next to the `users_color_check` CHECK
|
|
369
|
+
* that is rendered from it — pinning the list a second time in this package
|
|
370
|
+
* would be a second source of truth for what the database accepts, and the two
|
|
371
|
+
* would drift apart silently. What this shape does is keep an over-long or
|
|
372
|
+
* non-string value from reaching the service at all.
|
|
373
|
+
*/
|
|
374
|
+
color: zod_1.z.string().trim().max(32).optional(),
|
|
358
375
|
/** Ordered, PRIMARY FIRST — see rule 2 above {@link ACCOUNT_CATEGORY_IDS}. */
|
|
359
376
|
accountCategories: exports.accountCategoriesSchema.optional(),
|
|
377
|
+
/**
|
|
378
|
+
* Create the account already opted OUT of discovery.
|
|
379
|
+
*
|
|
380
|
+
* ## Why this belongs at CREATION and not only on the privacy route
|
|
381
|
+
*
|
|
382
|
+
* Every account is born discoverable: the column defaults to `false` and
|
|
383
|
+
* nothing on the create path wrote it, so a new account appears in people
|
|
384
|
+
* search the instant it exists. For a human signing themselves up that is the
|
|
385
|
+
* right default and it is NOT changed here. For an account a program creates
|
|
386
|
+
* on someone's behalf — an agent, an unlaunched project, an organization for
|
|
387
|
+
* something not yet announced — it publishes the thing before its owner ever
|
|
388
|
+
* decided to.
|
|
389
|
+
*
|
|
390
|
+
* The alternative is a second call right after create, which is a window in
|
|
391
|
+
* which the account IS public, and a window whose closing depends on a second
|
|
392
|
+
* request succeeding. A field here has neither: one statement, one row, born
|
|
393
|
+
* in the state the caller asked for.
|
|
394
|
+
*
|
|
395
|
+
* ## It reuses the existing flag deliberately
|
|
396
|
+
*
|
|
397
|
+
* This is `privacy_is_private_account`, the same one `PUT /users/:id/privacy`
|
|
398
|
+
* toggles — not a new "published" column. A second visibility flag would be a
|
|
399
|
+
* second source of truth for one question, and the two would disagree.
|
|
400
|
+
*
|
|
401
|
+
* Inherited semantics, stated because reusing a flag means inheriting ALL of
|
|
402
|
+
* it: the account is kept out of people search, out of the follow-graph lists
|
|
403
|
+
* (`followers` / `following` / `mutuals`), out of `/similar` and out of the
|
|
404
|
+
* recommendation candidate pools, and its non-public, non-unlisted media
|
|
405
|
+
* becomes follower-gated. It does NOT hide the profile from someone who knows
|
|
406
|
+
* the handle, and it carries NO follow-approval flow — following is immediate
|
|
407
|
+
* and unilateral whatever this says, so nothing here creates a request queue
|
|
408
|
+
* nobody attends.
|
|
409
|
+
*
|
|
410
|
+
* ## Not conditioned on `kind`, on purpose
|
|
411
|
+
*
|
|
412
|
+
* The same reasoning as `accountCategories` above: this object does not
|
|
413
|
+
* refine on kind, and an unlaunched organization has exactly the problem an
|
|
414
|
+
* unpublished agent does. The discovery predicate never reads `kind`, so the
|
|
415
|
+
* remedy must not either.
|
|
416
|
+
*/
|
|
417
|
+
isPrivateAccount: zod_1.z.boolean().optional(),
|
|
360
418
|
});
|
package/dist/cjs/index.js
CHANGED
|
@@ -17,9 +17,9 @@ exports.moderationDecisionEventSubjectSchema = exports.moderationFindingSchema =
|
|
|
17
17
|
exports.browserHubErrorSchema = exports.browserHubResolveResponseSchema = exports.browserHubHandleResponseSchema = exports.browserHubHandleRequestSchema = exports.browserHubHandleSchema = exports.BROWSER_HUB_HANDLE_TTL_MS = exports.BROWSER_HUB_COOKIE_ATTRIBUTES = exports.BROWSER_HUB_COOKIE_NAME = exports.oauthAuthorizeCodeResponseSchema = exports.oauthConsentDecisionSchema = exports.deviceDirectorySyncSchema = exports.deviceActivateResponseSchema = exports.deviceActivateRequestSchema = exports.deviceDirectorySchema = exports.devicePrincipalSchema = exports.deviceAccountContextSchema = exports.deviceDirectoryProfileSchema = exports.deviceContextRelationshipSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceBackgroundTokenResponseSchema = exports.deviceBackgroundTokenRequestSchema = exports.deviceBackgroundCredentialResponseSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = exports.applicationModerationTrustSchema = exports.reputationContextualInfluenceSchema = exports.reputationReviewingSchema = exports.reputationReportingSchema = exports.reputationConductSchema = exports.reputationContributionSchema = exports.reputationPersonhoodSchema = exports.identityBindingSchema = exports.registerIdentityBindingSchema = exports.reverseModerationEffectResultSchema = exports.applyModerationDecisionResultSchema = exports.moderationEffectSchema = exports.reverseModerationEffectSchema = exports.finalizeModerationDecisionSchema = exports.moderationDecisionEventSchema = exports.moderationPolicyVersionsSchema = void 0;
|
|
18
18
|
exports.deviceTransferApproveResponseSchema = exports.deviceTransferApproveRequestSchema = exports.deviceTransferInfoResponseSchema = exports.deviceTransferInitResponseSchema = exports.deviceTransferInitRequestSchema = exports.devicePairingStatusSchema = exports.webauthnLoginVerifyRequestSchema = exports.webauthnRegisterVerifyRequestSchema = exports.webauthnLoginOptionsRequestSchema = exports.webauthnRegisterOptionsRequestSchema = exports.updateRolloutPatchSchema = exports.promoteRequestSchema = exports.rollbackToEmbeddedRequestSchema = exports.rollbackRequestSchema = exports.updateListResponseSchema = exports.channelListResponseSchema = exports.channelSchema = exports.rollbackToEmbeddedEntrySchema = exports.createUpdateResponseSchema = exports.updateSchema = exports.createUpdateRequestSchema = exports.updateAssetRefSchema = exports.assetCompleteResponseSchema = exports.assetCompleteResultItemSchema = exports.assetCompleteRequestSchema = exports.assetInitResponseSchema = exports.assetUploadTicketSchema = exports.assetInitRequestSchema = exports.assetInitItemSchema = exports.rolloutPercentSchema = exports.runtimeVersionSchema = exports.channelNameSchema = exports.sha256HexSchema = exports.updateAssetStatusSchema = exports.updateStatusSchema = exports.updatePlatformSchema = exports.backupStatusResponseSchema = exports.backupUploadRequestSchema = exports.encryptedBackupEnvelopeSchema = exports.backupLookupIdSchema = exports.rotateKeyCompleteResponseSchema = exports.rotateKeyCompleteRequestSchema = exports.rotateKeyChallengeResponseSchema = exports.loginResultSchema = exports.hubAuthorizeResultSchema = exports.hubAuthorizeRequestSchema = exports.hubActivateRequestSchema = exports.hubClaimRequestSchema = exports.hubSessionSchema = exports.browserHubRevokeResponseSchema = void 0;
|
|
19
19
|
exports.providerErrorPassthroughSchema = exports.safeErrorTextSchema = exports.upstreamErrorCategorySchema = exports.inferenceErrorCodeSchema = exports.NON_RETRYABLE_INFERENCE_ERROR_CODES = exports.INFERENCE_ERROR_CODES = exports.inferenceAttributionSchema = exports.authenticatedPrincipalSchema = exports.billingPrincipalSchema = exports.inferenceScopeSchema = exports.INFERENCE_SCOPES = exports.unitPriceSchema = exports.usageQuantitySchema = exports.usageSourceSchema = exports.USAGE_SOURCES = exports.usageUnitSchema = exports.USAGE_UNITS = exports.moneySchema = exports.exactDecimalSchema = exports.INFERENCE_MONEY_SCALE = exports.currencyCodeSchema = exports.RESERVED_ALIA_PUBLISHER = exports.inferenceRegionSchema = exports.deploymentIdSchema = exports.inferenceProviderSlugSchema = exports.routingProfileSlugSchema = exports.modelReferenceSchema = exports.modelRevisionLabelSchema = exports.modelIdSchema = exports.modelSlugSchema = exports.publisherSlugSchema = exports.sha256DigestSchema = exports.inferenceHttpsUrlSchema = exports.inferenceDateSchema = exports.inferenceTimestampSchema = exports.inferenceEnvironmentSchema = exports.idempotencyKeySchema = exports.generationIdSchema = exports.requestIdSchema = exports.oxyCredentialIdSchema = exports.oxyApplicationIdSchema = exports.delegatedUserIdSchema = exports.oxyAccountIdSchema = exports.INFERENCE_CONTRACT_VERSION = exports.transparencyCheckpointListSchema = exports.transparencyInclusionProofSchema = exports.transparencyCheckpointSchema = exports.transparencyAnchorSchema = exports.transparencyCheckpointSignatureSchema = exports.deviceTransferDenyResponseSchema = void 0;
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.productEntitlementSchema = exports.costCenterSpendSchema = exports.costCenterSchema = exports.costCenterStatusSchema = exports.COST_CENTER_STATUSES = exports.payAsYouGoEntitlementSchema = void 0;
|
|
20
|
+
exports.samplingParametersSchema = exports.inferenceInputSchema = exports.inferenceMessageSchema = exports.inferenceMessageRoleSchema = exports.inferenceToolCallSchema = exports.inferenceContentPartSchema = exports.inferenceContentSourceSchema = exports.modelDocumentationSchema = exports.modelReleaseIngestionResultSchema = exports.modelReleaseIngestionRequestSchema = exports.modelLineDeclarationSchema = exports.modelGpaiDocumentationSchema = exports.modelDownstreamDocumentationSchema = exports.SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS = exports.trainingComputeFlopsSchema = exports.modelSystemicRiskTierSchema = exports.modelDistributionMethodSchema = exports.aliaModelReleaseManifestSchema = exports.aliaReleaseSignatureSchema = exports.aliaReleaseArtifactSchema = exports.authorizedRouteSchema = exports.routingPolicyReferenceSchema = exports.routingPolicySchema = exports.routingFallbackPolicySchema = exports.routingPolicyScopeSchema = exports.routingTargetSchema = exports.modelCatalogueEntrySchema = exports.catalogueServingProviderSummarySchema = exports.cataloguePublisherSummarySchema = exports.routingProfileSchema = exports.routingProfileCandidateSchema = exports.modelDeploymentSchema = exports.inferenceProviderSchema = exports.modelRevisionSchema = exports.catalogueModelSchema = exports.modelPublisherSchema = exports.modelSafetyMetadataSchema = exports.modelEvaluationResultSchema = exports.modelDeprecationSchema = exports.commercialPermissionSchema = exports.availabilityScopeSchema = exports.inferenceDataPolicySchema = exports.modelProvenanceSchema = exports.modelLicenseSchema = exports.modelCapabilitiesSchema = exports.inferenceModalitySchema = exports.priceSnapshotSchema = exports.priceVersionSchema = exports.priceVersionStatusSchema = exports.inferenceErrorSchema = void 0;
|
|
21
|
+
exports.RECONCILIATION_DISCREPANCY_KINDS = exports.autoRechargeAttemptSchema = exports.autoRechargeStatusSchema = exports.AUTO_RECHARGE_STATUSES = exports.externalPaymentSchema = exports.externalPaymentKindSchema = exports.EXTERNAL_PAYMENT_KINDS = exports.externalPaymentProviderSchema = exports.EXTERNAL_PAYMENT_PROVIDERS = exports.billingInvoiceSchema = exports.billingInvoiceStatusSchema = exports.BILLING_INVOICE_STATUSES = exports.accountBillingStateSchema = exports.billingProfileSchema = exports.autoRechargeSchema = exports.billingProfileStatusSchema = exports.BILLING_PROFILE_STATUSES = exports.billingModeSchema = exports.BILLING_MODES = exports.providerConnectionSchema = exports.providerConnectionStatusSchema = exports.providerConnectionValidationSchema = exports.providerSecretReferenceSchema = exports.providerConnectionScopeSchema = exports.PROVIDER_SECRET_REFERENCE_NAMESPACE = exports.usageRefundSchema = exports.usageRefundReasonSchema = exports.usageRefundSubjectSchema = exports.usageReceiptSchema = exports.normalizedUsageReportSchema = exports.inferenceRequestOutcomeSchema = exports.usageReservationSchema = exports.usageReservationStatusSchema = exports.usageReservationRequestSchema = exports.inferenceStreamEventSchema = exports.inferenceStreamDoneEventSchema = exports.inferenceFinishReasonSchema = exports.inferenceStreamErrorEventSchema = exports.inferenceStreamRouteSwitchEventSchema = exports.inferenceRouteSwitchReasonSchema = exports.inferenceRouteSwitchDetailSchema = exports.inferenceStreamUsageEventSchema = exports.inferenceStreamToolCallEventSchema = exports.inferenceStreamDeltaEventSchema = exports.inferenceStreamStartEventSchema = exports.inferenceRequestSchema = exports.clientRequestMetadataSchema = exports.responseFormatSchema = exports.toolChoiceSchema = exports.toolDefinitionSchema = void 0;
|
|
22
|
+
exports.productEntitlementSchema = exports.costCenterSpendSchema = exports.costCenterSchema = exports.costCenterStatusSchema = exports.COST_CENTER_STATUSES = exports.payAsYouGoEntitlementSchema = exports.productPlanSchema = exports.planAllowanceSchema = exports.LIVE_PRODUCT_PLAN_STATUSES = exports.productPlanStatusSchema = exports.PRODUCT_PLAN_STATUSES = exports.reconciliationReportSchema = exports.reconciliationRunSchema = exports.reconciliationDiscrepancySchema = exports.reconciliationRunStatusSchema = exports.RECONCILIATION_RUN_STATUSES = exports.reconciliationDiscrepancyKindSchema = void 0;
|
|
23
23
|
var accountGraph_1 = require("./accountGraph");
|
|
24
24
|
Object.defineProperty(exports, "ACCOUNT_KINDS", { enumerable: true, get: function () { return accountGraph_1.ACCOUNT_KINDS; } });
|
|
25
25
|
Object.defineProperty(exports, "accountKindSchema", { enumerable: true, get: function () { return accountGraph_1.accountKindSchema; } });
|
|
@@ -440,6 +440,20 @@ var aliaModelRelease_1 = require("./inference/aliaModelRelease");
|
|
|
440
440
|
Object.defineProperty(exports, "aliaReleaseArtifactSchema", { enumerable: true, get: function () { return aliaModelRelease_1.aliaReleaseArtifactSchema; } });
|
|
441
441
|
Object.defineProperty(exports, "aliaReleaseSignatureSchema", { enumerable: true, get: function () { return aliaModelRelease_1.aliaReleaseSignatureSchema; } });
|
|
442
442
|
Object.defineProperty(exports, "aliaModelReleaseManifestSchema", { enumerable: true, get: function () { return aliaModelRelease_1.aliaModelReleaseManifestSchema; } });
|
|
443
|
+
var modelDocumentation_1 = require("./inference/modelDocumentation");
|
|
444
|
+
// Model documentation: the GPAI/EU AI Act record, the ingestion request that
|
|
445
|
+
// accepts it beside a signed manifest, and the revision-scoped documentation
|
|
446
|
+
// view a downstream developer reads.
|
|
447
|
+
Object.defineProperty(exports, "modelDistributionMethodSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelDistributionMethodSchema; } });
|
|
448
|
+
Object.defineProperty(exports, "modelSystemicRiskTierSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelSystemicRiskTierSchema; } });
|
|
449
|
+
Object.defineProperty(exports, "trainingComputeFlopsSchema", { enumerable: true, get: function () { return modelDocumentation_1.trainingComputeFlopsSchema; } });
|
|
450
|
+
Object.defineProperty(exports, "SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS", { enumerable: true, get: function () { return modelDocumentation_1.SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS; } });
|
|
451
|
+
Object.defineProperty(exports, "modelDownstreamDocumentationSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelDownstreamDocumentationSchema; } });
|
|
452
|
+
Object.defineProperty(exports, "modelGpaiDocumentationSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelGpaiDocumentationSchema; } });
|
|
453
|
+
Object.defineProperty(exports, "modelLineDeclarationSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelLineDeclarationSchema; } });
|
|
454
|
+
Object.defineProperty(exports, "modelReleaseIngestionRequestSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelReleaseIngestionRequestSchema; } });
|
|
455
|
+
Object.defineProperty(exports, "modelReleaseIngestionResultSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelReleaseIngestionResultSchema; } });
|
|
456
|
+
Object.defineProperty(exports, "modelDocumentationSchema", { enumerable: true, get: function () { return modelDocumentation_1.modelDocumentationSchema; } });
|
|
443
457
|
var request_1 = require("./inference/request");
|
|
444
458
|
// The normalized Oxy→data-plane request envelope.
|
|
445
459
|
Object.defineProperty(exports, "inferenceContentSourceSchema", { enumerable: true, get: function () { return request_1.inferenceContentSourceSchema; } });
|
|
@@ -480,6 +494,7 @@ Object.defineProperty(exports, "usageRefundReasonSchema", { enumerable: true, ge
|
|
|
480
494
|
Object.defineProperty(exports, "usageRefundSchema", { enumerable: true, get: function () { return usage_1.usageRefundSchema; } });
|
|
481
495
|
var providerConnection_1 = require("./inference/providerConnection");
|
|
482
496
|
// BYOK connection metadata that structurally cannot carry a secret.
|
|
497
|
+
Object.defineProperty(exports, "PROVIDER_SECRET_REFERENCE_NAMESPACE", { enumerable: true, get: function () { return providerConnection_1.PROVIDER_SECRET_REFERENCE_NAMESPACE; } });
|
|
483
498
|
Object.defineProperty(exports, "providerConnectionScopeSchema", { enumerable: true, get: function () { return providerConnection_1.providerConnectionScopeSchema; } });
|
|
484
499
|
Object.defineProperty(exports, "providerSecretReferenceSchema", { enumerable: true, get: function () { return providerConnection_1.providerSecretReferenceSchema; } });
|
|
485
500
|
Object.defineProperty(exports, "providerConnectionValidationSchema", { enumerable: true, get: function () { return providerConnection_1.providerConnectionValidationSchema; } });
|
|
@@ -36,14 +36,22 @@
|
|
|
36
36
|
* bounded: ingestion is a release-time operation an operator retries once Oxy
|
|
37
37
|
* takes the newer contract, not a served request that becomes unsettleable.
|
|
38
38
|
*
|
|
39
|
-
* ##
|
|
39
|
+
* ## The ingestion path, which this file used to say did not exist
|
|
40
|
+
*
|
|
41
|
+
* It does now: `POST /inference/admin/model-releases`, defined by
|
|
42
|
+
* `modelReleaseIngestionRequestSchema` in `modelDocumentation.ts`. This shape is
|
|
43
|
+
* unchanged — the request COMPOSES it, alongside two records that are Oxy's own
|
|
44
|
+
* rather than the signer's (the GPAI documentation and the capability sheet a
|
|
45
|
+
* manifest does not carry), precisely so the bytes a signature covers stay
|
|
46
|
+
* exactly the bytes described here.
|
|
40
47
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
48
|
+
* The earlier objection was that a staff write path into an empty catalogue is
|
|
49
|
+
* an unexercised hazard. What answers it is containment rather than emptiness: an
|
|
50
|
+
* ingested revision lands with `is_current = false` and no deployment, so nothing
|
|
51
|
+
* it creates is servable or listed, and a route still needs an approved
|
|
52
|
+
* contract/legal review before any customer can select it.
|
|
53
|
+
*
|
|
54
|
+
* ## What is deliberately NOT here
|
|
47
55
|
*
|
|
48
56
|
* **No `payloadDigest` field.** The signature is over the canonical
|
|
49
57
|
* serialization of this manifest with `signatures` removed, and a verifier
|
|
@@ -65,7 +73,11 @@
|
|
|
65
73
|
* custody, rotation and revocation consequences. So `keyId` is an OPAQUE
|
|
66
74
|
* identifier and this file names no registry that resolves it: either answer
|
|
67
75
|
* fits, and neither is presupposed. Until it is answered a manifest can be
|
|
68
|
-
* parsed and cannot be
|
|
76
|
+
* parsed and cannot be VERIFIED, so the ingestion path records no verification
|
|
77
|
+
* finding at all: it stores the signatures and the manifest as received, and the
|
|
78
|
+
* authority for the ingest is the staff member who performed it. A nullable
|
|
79
|
+
* `verified` column nothing ever writes would read, to whoever scanned the table
|
|
80
|
+
* later, as a check that ran.
|
|
69
81
|
*
|
|
70
82
|
* Decided in: docs/adr/0008-catalogue-concept-separation.md,
|
|
71
83
|
* docs/adr/0017-authorized-routes-in-the-envelope.md, issue #972 §12.
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Model documentation: what a first-party release must DECLARE, what a
|
|
4
|
+
* downstream developer may READ, and the request that ingests both.
|
|
5
|
+
*
|
|
6
|
+
* Issue #972 §12, the three items under "Future Alia model
|
|
7
|
+
* publication/compliance" that `aliaModelRelease.ts` deliberately left open:
|
|
8
|
+
* accepting the documentation set, publicising the customer-safe half of it, and
|
|
9
|
+
* preserving the metadata an EU AI Act / GPAI documentation workflow needs.
|
|
10
|
+
*
|
|
11
|
+
* ## The section's own scope is what makes the compliance claim falsifiable
|
|
12
|
+
*
|
|
13
|
+
* The issue section is titled "Future Alia model publication/compliance", so the
|
|
14
|
+
* obligations in play are the ones binding a PROVIDER of a general-purpose AI
|
|
15
|
+
* model — Oxy/Alia, for an `alia/*` release it trained or derived. Oxy's position
|
|
16
|
+
* on third-party weights is a different one (it received documentation rather
|
|
17
|
+
* than produced it) with different obligations, and nothing here claims to
|
|
18
|
+
* discharge those. Every field below names the obligation it serves; a field
|
|
19
|
+
* whose obligation could not be named is not here, and two are listed at the
|
|
20
|
+
* bottom as deliberately absent.
|
|
21
|
+
*
|
|
22
|
+
* References are to Regulation (EU) 2024/1689 (the AI Act): Article 50(2)
|
|
23
|
+
* (marking synthetic output), Article 51 (classification as a model with
|
|
24
|
+
* systemic risk), Article 53 (obligations of providers of general-purpose AI
|
|
25
|
+
* models), Article 55 (additional obligations for systemic-risk models), Annex XI
|
|
26
|
+
* (the technical documentation), Annex XII (the information for downstream
|
|
27
|
+
* providers).
|
|
28
|
+
*
|
|
29
|
+
* ## Two shapes, and the Act itself draws the line between them
|
|
30
|
+
*
|
|
31
|
+
* {@link modelGpaiDocumentationSchema} is the whole record. {@link
|
|
32
|
+
* modelDownstreamDocumentationSchema} is the subset served publicly. The split
|
|
33
|
+
* is NOT editorial taste: Annex XI is documentation a provider keeps and
|
|
34
|
+
* provides to the AI Office and national competent authorities on request, while
|
|
35
|
+
* Annex XII is information a provider MAKES AVAILABLE to downstream providers.
|
|
36
|
+
* Training compute, training time, energy consumption and the adversarial-testing
|
|
37
|
+
* report are Annex XI Section 2 and Article 55(1)(a) — the first audience — so
|
|
38
|
+
* they are in the record and not in the public projection, and
|
|
39
|
+
* `db/schema/protectedColumns.ts` says the same thing a second time at the type
|
|
40
|
+
* level.
|
|
41
|
+
*
|
|
42
|
+
* ## The conditionals are the Act's, not a convenience
|
|
43
|
+
*
|
|
44
|
+
* Article 53(2) exempts a model released under a free and open-source licence
|
|
45
|
+
* from 53(1)(a) and 53(1)(b) — the Annex XI and Annex XII sets — UNLESS it is a
|
|
46
|
+
* model with systemic risk. It does not exempt 53(1)(c) or 53(1)(d). So the
|
|
47
|
+
* copyright policy and the training-content summary are required of every
|
|
48
|
+
* release here, while the Annex XI/XII set is required of every release that is
|
|
49
|
+
* not covered by that exemption. Writing it the other way round — everything
|
|
50
|
+
* optional, checked by a human — is what makes a compliance record a field nobody
|
|
51
|
+
* filled in.
|
|
52
|
+
*
|
|
53
|
+
* ## What is deliberately NOT here
|
|
54
|
+
*
|
|
55
|
+
* **The modality and FORMAT of inputs and outputs (Annex XI §1(6), Annex XII
|
|
56
|
+
* §1(b)).** The modality half is already stored, as `inference_models`'
|
|
57
|
+
* `input_modalities` / `output_modalities`. The format half is a property of the
|
|
58
|
+
* Oxy API — one request envelope, one set of endpoints, identical for every model
|
|
59
|
+
* — so a per-model column would record the same value on every row and invite a
|
|
60
|
+
* reader to believe it could differ.
|
|
61
|
+
*
|
|
62
|
+
* **The technical means required for integration (Annex XII §1(c)).** Same
|
|
63
|
+
* reason: for a model served over the Oxy API that is Oxy's own API
|
|
64
|
+
* documentation, not a fact about the weights.
|
|
65
|
+
*
|
|
66
|
+
* **A verification finding for a release signature.** See
|
|
67
|
+
* `aliaModelRelease.ts`: whether a signature checked out is Oxy's finding about
|
|
68
|
+
* the document and not a claim the document makes, and no verifier exists yet
|
|
69
|
+
* because what signs is undecided. The ingestion path stores the signatures and
|
|
70
|
+
* the manifest as received so a verifier that lands later can check them; it
|
|
71
|
+
* records no finding, because there is none.
|
|
72
|
+
*
|
|
73
|
+
* Decided in: docs/adr/0008-catalogue-concept-separation.md, issue #972 §12.
|
|
74
|
+
*/
|
|
75
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76
|
+
exports.modelDocumentationSchema = exports.modelReleaseIngestionResultSchema = exports.modelReleaseIngestionRequestSchema = exports.modelLineDeclarationSchema = exports.modelGpaiDocumentationSchema = exports.modelDownstreamDocumentationSchema = exports.SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS = exports.trainingComputeFlopsSchema = exports.modelSystemicRiskTierSchema = exports.modelDistributionMethodSchema = void 0;
|
|
77
|
+
const zod_1 = require("zod");
|
|
78
|
+
const aliaModelRelease_1 = require("./aliaModelRelease");
|
|
79
|
+
const catalogue_1 = require("./catalogue");
|
|
80
|
+
const identifiers_1 = require("./identifiers");
|
|
81
|
+
/* -------------------------------------------------------------------------- */
|
|
82
|
+
/* Vocabulary */
|
|
83
|
+
/* -------------------------------------------------------------------------- */
|
|
84
|
+
/**
|
|
85
|
+
* How a release reaches the people who use it — Annex XI §1(4) and Annex XII
|
|
86
|
+
* §1(a), "methods of distribution".
|
|
87
|
+
*
|
|
88
|
+
* TWO members, and both exist today: a release is served through the Oxy API, or
|
|
89
|
+
* its weights are published for download, or both. A third channel is a
|
|
90
|
+
* distribution decision somebody would have to make, and a closed enum gaining a
|
|
91
|
+
* member is a MINOR contract-set change the handshake surfaces (`version.ts`),
|
|
92
|
+
* which is the right amount of ceremony for it.
|
|
93
|
+
*
|
|
94
|
+
* `downloadable_weights` is also what the Article 53(2) free-and-open-source
|
|
95
|
+
* exemption is assessed against — that exemption requires the model to be
|
|
96
|
+
* "released under a free and open-source licence that allows for the access,
|
|
97
|
+
* usage, modification and distribution of the model" — so it is required even
|
|
98
|
+
* where the Annex XI set it belongs to is exempt.
|
|
99
|
+
*/
|
|
100
|
+
exports.modelDistributionMethodSchema = zod_1.z.enum(['oxy_api', 'downloadable_weights']);
|
|
101
|
+
/**
|
|
102
|
+
* Whether this is a model with systemic risk, and on what basis — Article 51.
|
|
103
|
+
*
|
|
104
|
+
* Three states, because the two ways a model acquires the classification have
|
|
105
|
+
* different evidence and a record that flattened them could not be checked:
|
|
106
|
+
*
|
|
107
|
+
* - `not_designated` — neither presumed nor designated.
|
|
108
|
+
* - `presumed_by_training_compute` — Article 51(2): the cumulative compute used
|
|
109
|
+
* for training exceeds 10^25 floating point operations, which the Act makes a
|
|
110
|
+
* presumption of high-impact capabilities. The FIGURE is what creates it, so
|
|
111
|
+
* {@link modelGpaiDocumentationSchema} requires the figure alongside this
|
|
112
|
+
* value.
|
|
113
|
+
* - `designated_by_commission` — Article 51(1)(b): a Commission decision, ex
|
|
114
|
+
* officio or following a qualified alert, that the model has capabilities
|
|
115
|
+
* equivalent to the presumption. Not derivable from anything Oxy holds, which
|
|
116
|
+
* is exactly why it is a declared value.
|
|
117
|
+
*/
|
|
118
|
+
exports.modelSystemicRiskTierSchema = zod_1.z.enum([
|
|
119
|
+
'not_designated',
|
|
120
|
+
'presumed_by_training_compute',
|
|
121
|
+
'designated_by_commission',
|
|
122
|
+
]);
|
|
123
|
+
/**
|
|
124
|
+
* Cumulative training compute in floating point operations — Annex XI §2(b).
|
|
125
|
+
*
|
|
126
|
+
* TEXT, in the same spirit as `modelEvaluationResultSchema.score` and for a
|
|
127
|
+
* sharper reason: this is a PUBLISHED figure (`4.2e25`, `2.5e26`), the numbers
|
|
128
|
+
* involved are far outside the exactly-representable integer range, and the
|
|
129
|
+
* value is never arithmetic Oxy performs on a customer's behalf. A JSON number
|
|
130
|
+
* would round it silently and make two records of one published figure compare
|
|
131
|
+
* unequal.
|
|
132
|
+
*
|
|
133
|
+
* The one comparison that IS made — against Article 51(2)'s 10^25 threshold — is
|
|
134
|
+
* a magnitude test, and `Number()` on a string this regex admits is exact enough
|
|
135
|
+
* for a magnitude test by a factor of about 10^9. The refinement that performs
|
|
136
|
+
* it is on {@link modelGpaiDocumentationSchema}.
|
|
137
|
+
*/
|
|
138
|
+
exports.trainingComputeFlopsSchema = zod_1.z
|
|
139
|
+
.string()
|
|
140
|
+
.max(40)
|
|
141
|
+
.regex(/^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:e\+?(?:0|[1-9][0-9]?))?$/, 'training compute must be a decimal or scientific figure, e.g. 4.2e25');
|
|
142
|
+
/**
|
|
143
|
+
* Article 51(2)'s presumption threshold, as a number.
|
|
144
|
+
*
|
|
145
|
+
* Named rather than inlined so the refinement that applies it and the enum
|
|
146
|
+
* member that describes it (`presumed_by_training_compute`) cannot come to mean
|
|
147
|
+
* different things.
|
|
148
|
+
*/
|
|
149
|
+
exports.SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS = 1e25;
|
|
150
|
+
/* -------------------------------------------------------------------------- */
|
|
151
|
+
/* The record */
|
|
152
|
+
/* -------------------------------------------------------------------------- */
|
|
153
|
+
/**
|
|
154
|
+
* The subset of the documentation set that is served to downstream developers —
|
|
155
|
+
* Annex XII, plus the two Article 53(1) items that are public by their own terms.
|
|
156
|
+
*
|
|
157
|
+
* Rides inside {@link modelDocumentationSchema} and inherits its version.
|
|
158
|
+
*
|
|
159
|
+
* Every field here is one a developer integrating the model needs in order to
|
|
160
|
+
* decide whether they may use it and what they must say about it: what it is for,
|
|
161
|
+
* how it is distributed, what it is built out of, where the training-content
|
|
162
|
+
* summary and the copyright policy are, and whether it carries the systemic-risk
|
|
163
|
+
* classification that puts obligations on them too.
|
|
164
|
+
*
|
|
165
|
+
* The optional members are optional for a REASON stated in the parent record's
|
|
166
|
+
* refinement — Article 53(2) — and not because a value may be skipped.
|
|
167
|
+
*/
|
|
168
|
+
exports.modelDownstreamDocumentationSchema = zod_1.z
|
|
169
|
+
.object({
|
|
170
|
+
/** Annex XI §1(2), Annex XII §1(a): the tasks the model is intended for. */
|
|
171
|
+
intendedTasks: zod_1.z.string().min(1).max(2000).optional(),
|
|
172
|
+
/** Annex XI §1(4), Annex XII §1(a). */
|
|
173
|
+
distributionMethods: zod_1.z.array(exports.modelDistributionMethodSchema).min(1),
|
|
174
|
+
/** Annex XI §1(5), reachable through Annex XII §1(a) ("points 1 to 5"). */
|
|
175
|
+
architecture: zod_1.z.string().min(1).max(500).optional(),
|
|
176
|
+
/** Annex XI §1(5): the number of parameters. */
|
|
177
|
+
parameterCount: zod_1.z.number().int().positive().safe().optional(),
|
|
178
|
+
/** Article 53(1)(d): the publicly available summary of training content. */
|
|
179
|
+
trainingDataSummaryUrl: identifiers_1.inferenceHttpsUrlSchema,
|
|
180
|
+
/**
|
|
181
|
+
* Article 53(1)(c): the policy for complying with Union copyright law,
|
|
182
|
+
* including the reservation of rights under Article 4(3) of Directive
|
|
183
|
+
* (EU) 2019/790. Required of every release — Article 53(2) does not exempt it.
|
|
184
|
+
*/
|
|
185
|
+
copyrightPolicyUrl: identifiers_1.inferenceHttpsUrlSchema,
|
|
186
|
+
/** Article 51. */
|
|
187
|
+
systemicRisk: exports.modelSystemicRiskTierSchema,
|
|
188
|
+
/**
|
|
189
|
+
* Whether the release is under a free and open-source licence in the sense
|
|
190
|
+
* of Article 53(2). Distinct from `modelLicenseSchema.commercialUseAllowed`,
|
|
191
|
+
* which answers whether OXY may serve the model — a licence can permit
|
|
192
|
+
* commercial use and still not permit access, modification and
|
|
193
|
+
* redistribution of the weights, and it is the second question the exemption
|
|
194
|
+
* turns on.
|
|
195
|
+
*/
|
|
196
|
+
freeAndOpenSourceRelease: zod_1.z.boolean(),
|
|
197
|
+
})
|
|
198
|
+
.strict();
|
|
199
|
+
/**
|
|
200
|
+
* The whole documentation record for one revision, as ingested.
|
|
201
|
+
*
|
|
202
|
+
* `.strict()`, because this is a compliance record arriving over the wire: a
|
|
203
|
+
* field silently dropped at the parse is a field the record does not contain,
|
|
204
|
+
* and "we accepted your documentation" would then be true of less than was sent.
|
|
205
|
+
*
|
|
206
|
+
* Not versioned on its own — it rides inside
|
|
207
|
+
* {@link modelReleaseIngestionRequestSchema} on the way in and inside
|
|
208
|
+
* {@link modelDocumentationSchema} on the way out, and inherits whichever
|
|
209
|
+
* message carries it.
|
|
210
|
+
*/
|
|
211
|
+
exports.modelGpaiDocumentationSchema = exports.modelDownstreamDocumentationSchema
|
|
212
|
+
.extend({
|
|
213
|
+
/** Annex XI §2(b): the computational resources used for training. */
|
|
214
|
+
trainingComputeFlops: exports.trainingComputeFlopsSchema.optional(),
|
|
215
|
+
/** Annex XI §2(b): the training time. */
|
|
216
|
+
trainingTimeHours: zod_1.z.number().positive().safe().optional(),
|
|
217
|
+
/**
|
|
218
|
+
* Annex XI §2(c): the known or ESTIMATED energy consumption. The Act asks
|
|
219
|
+
* for an estimate where the figure is not known, so absence here means the
|
|
220
|
+
* Annex XI set is exempt rather than that the number was hard to obtain.
|
|
221
|
+
*/
|
|
222
|
+
energyConsumptionMwh: zod_1.z.number().nonnegative().safe().optional(),
|
|
223
|
+
/**
|
|
224
|
+
* Article 55(1)(a): the model evaluation, including adversarial testing,
|
|
225
|
+
* performed for a model with systemic risk. A pointer, like every other
|
|
226
|
+
* document reference here — the catalogue holds no report.
|
|
227
|
+
*/
|
|
228
|
+
adversarialTestingReportUrl: identifiers_1.inferenceHttpsUrlSchema.optional(),
|
|
229
|
+
})
|
|
230
|
+
.strict()
|
|
231
|
+
.superRefine((documentation, ctx) => {
|
|
232
|
+
// Article 53(2): the free-and-open-source exemption from 53(1)(a) and (b)
|
|
233
|
+
// does not apply to a model with systemic risk. So the Annex XI/XII set is
|
|
234
|
+
// required of everything else, and the ONE state that may omit it is a
|
|
235
|
+
// free-and-open-source release that is not designated.
|
|
236
|
+
const exempt = documentation.freeAndOpenSourceRelease && documentation.systemicRisk === 'not_designated';
|
|
237
|
+
if (!exempt) {
|
|
238
|
+
const required = [
|
|
239
|
+
'intendedTasks',
|
|
240
|
+
'architecture',
|
|
241
|
+
'parameterCount',
|
|
242
|
+
'trainingTimeHours',
|
|
243
|
+
'energyConsumptionMwh',
|
|
244
|
+
];
|
|
245
|
+
for (const field of required) {
|
|
246
|
+
if (documentation[field] === undefined) {
|
|
247
|
+
ctx.addIssue({
|
|
248
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
249
|
+
path: [field],
|
|
250
|
+
message: 'required by Annex XI unless the Article 53(2) free-and-open-source exemption applies, which it does not for this release',
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// The presumption IS the compute figure (Article 51(2)). Declaring the tier
|
|
256
|
+
// without the figure asserts a threshold was crossed while withholding the
|
|
257
|
+
// only thing that says so.
|
|
258
|
+
if (documentation.systemicRisk === 'presumed_by_training_compute' &&
|
|
259
|
+
documentation.trainingComputeFlops === undefined) {
|
|
260
|
+
ctx.addIssue({
|
|
261
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
262
|
+
path: ['trainingComputeFlops'],
|
|
263
|
+
message: 'a systemic-risk presumption under Article 51(2) is the training-compute figure; declare it',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// The other direction, which is the one that matters: a release whose own
|
|
267
|
+
// declared compute is past the threshold cannot also declare that no
|
|
268
|
+
// classification applies. Without this the field pair would let the record
|
|
269
|
+
// contradict itself and still parse.
|
|
270
|
+
if (documentation.trainingComputeFlops !== undefined &&
|
|
271
|
+
documentation.systemicRisk === 'not_designated' &&
|
|
272
|
+
Number(documentation.trainingComputeFlops) >= exports.SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS) {
|
|
273
|
+
ctx.addIssue({
|
|
274
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
275
|
+
path: ['systemicRisk'],
|
|
276
|
+
message: 'training compute at or above 10^25 FLOP is presumed to be a model with systemic risk under Article 51(2)',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
// Article 55(1)(a) applies to every model with systemic risk, however it
|
|
280
|
+
// acquired the classification.
|
|
281
|
+
if (documentation.systemicRisk !== 'not_designated' &&
|
|
282
|
+
documentation.adversarialTestingReportUrl === undefined) {
|
|
283
|
+
ctx.addIssue({
|
|
284
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
285
|
+
path: ['adversarialTestingReportUrl'],
|
|
286
|
+
message: 'a model with systemic risk documents its evaluation including adversarial testing (Article 55(1)(a))',
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
/* -------------------------------------------------------------------------- */
|
|
291
|
+
/* Ingestion */
|
|
292
|
+
/* -------------------------------------------------------------------------- */
|
|
293
|
+
/**
|
|
294
|
+
* What OXY states about the model line a release belongs to.
|
|
295
|
+
*
|
|
296
|
+
* A signed release manifest carries a revision, a licence, a provenance block,
|
|
297
|
+
* evaluations, safety metadata and an artifact inventory. It carries no
|
|
298
|
+
* CAPABILITY SHEET — no modalities, no `maxContextTokens`, none of the
|
|
299
|
+
* tool/streaming flags — and every one of those is required to create a model
|
|
300
|
+
* line at all.
|
|
301
|
+
*
|
|
302
|
+
* That is not a gap in the manifest. A capability sheet is a statement about what
|
|
303
|
+
* the Oxy API will serve, which is Oxy's to make and not the signer's: the same
|
|
304
|
+
* weights behind a different gateway answer a different set of these questions.
|
|
305
|
+
* So it travels beside the manifest, like the documentation record, and the
|
|
306
|
+
* signature keeps covering exactly the document its signer wrote.
|
|
307
|
+
*
|
|
308
|
+
* Ignored when the model line already exists — a release does not edit a model.
|
|
309
|
+
* The licence and provenance in the MANIFEST are checked against the stored ones
|
|
310
|
+
* instead, because those are claims about somebody's rights rather than Oxy's own
|
|
311
|
+
* editorial choices.
|
|
312
|
+
*/
|
|
313
|
+
exports.modelLineDeclarationSchema = zod_1.z
|
|
314
|
+
.object({
|
|
315
|
+
displayName: zod_1.z.string().min(1).max(200),
|
|
316
|
+
description: zod_1.z.string().max(4000).optional(),
|
|
317
|
+
capabilities: catalogue_1.modelCapabilitiesSchema,
|
|
318
|
+
knowledgeCutoff: identifiers_1.inferenceDateSchema.optional(),
|
|
319
|
+
releasedOn: identifiers_1.inferenceDateSchema.optional(),
|
|
320
|
+
})
|
|
321
|
+
.strict();
|
|
322
|
+
/**
|
|
323
|
+
* The body of the release-ingestion request.
|
|
324
|
+
*
|
|
325
|
+
* The documentation and the capability sheet travel BESIDE the manifest rather
|
|
326
|
+
* than inside it, and that is the whole reason this wrapper exists.
|
|
327
|
+
* `aliaModelReleaseManifestSchema` is a SIGNED document: adding a field to it
|
|
328
|
+
* would change the bytes a signer covers and the version the data plane and Alia
|
|
329
|
+
* compile against, for records that are Oxy's own rather than the signer's.
|
|
330
|
+
* Keeping them separate means the signature still covers exactly what it covered.
|
|
331
|
+
*
|
|
332
|
+
* A signer that later chooses to cover the documentation too can: it would
|
|
333
|
+
* become a second signed document with its own manifest, which is a contract
|
|
334
|
+
* addition rather than a change to this one.
|
|
335
|
+
*/
|
|
336
|
+
exports.modelReleaseIngestionRequestSchema = zod_1.z
|
|
337
|
+
.object({
|
|
338
|
+
/** See `version.ts`: an ingestion payload is a whole message on the wire. */
|
|
339
|
+
schemaVersion: zod_1.z.literal(1),
|
|
340
|
+
manifest: aliaModelRelease_1.aliaModelReleaseManifestSchema,
|
|
341
|
+
gpaiDocumentation: exports.modelGpaiDocumentationSchema,
|
|
342
|
+
model: exports.modelLineDeclarationSchema,
|
|
343
|
+
})
|
|
344
|
+
.strict();
|
|
345
|
+
/**
|
|
346
|
+
* What ingestion reports back.
|
|
347
|
+
*
|
|
348
|
+
* COUNTS for the artifacts and signatures rather than echoing them: the caller
|
|
349
|
+
* sent them and the interesting fact is that all of them landed. Echoing a
|
|
350
|
+
* signature would also make this response a place a credential-shaped value gets
|
|
351
|
+
* logged, for no gain.
|
|
352
|
+
*
|
|
353
|
+
* No verification field — see this module's header, and `aliaModelRelease.ts`.
|
|
354
|
+
*/
|
|
355
|
+
exports.modelReleaseIngestionResultSchema = zod_1.z
|
|
356
|
+
.object({
|
|
357
|
+
/** See `version.ts`: served on its own, so it is versioned. */
|
|
358
|
+
schemaVersion: zod_1.z.literal(1),
|
|
359
|
+
releaseId: zod_1.z.string().min(1).max(128),
|
|
360
|
+
modelId: identifiers_1.modelIdSchema,
|
|
361
|
+
revision: identifiers_1.modelRevisionLabelSchema,
|
|
362
|
+
reference: identifiers_1.modelReferenceSchema,
|
|
363
|
+
/** Whether this request created the release, or found it already ingested. */
|
|
364
|
+
outcome: zod_1.z.enum(['ingested', 'already_ingested']),
|
|
365
|
+
artifactCount: zod_1.z.number().int().positive().safe(),
|
|
366
|
+
signatureCount: zod_1.z.number().int().positive().safe(),
|
|
367
|
+
evaluationCount: zod_1.z.number().int().nonnegative().safe(),
|
|
368
|
+
ingestedAt: identifiers_1.inferenceTimestampSchema,
|
|
369
|
+
})
|
|
370
|
+
.strict();
|
|
371
|
+
/* -------------------------------------------------------------------------- */
|
|
372
|
+
/* The customer-safe documentation view */
|
|
373
|
+
/* -------------------------------------------------------------------------- */
|
|
374
|
+
/**
|
|
375
|
+
* The documentation for ONE revision, as a downstream developer reads it.
|
|
376
|
+
*
|
|
377
|
+
* Revision-scoped, and that is the point of it existing beside
|
|
378
|
+
* `modelCatalogueEntrySchema`. The catalogue entry carries the documentation of
|
|
379
|
+
* whichever revision is CURRENT, so a customer who pinned
|
|
380
|
+
* `<publisher>/<model>@<revision>` — which the catalogue invites, and which the
|
|
381
|
+
* immutability trigger on `inference_model_revisions` exists to make meaningful —
|
|
382
|
+
* had no way to read the model card, evaluations or safety metadata of the
|
|
383
|
+
* revision they are actually calling. A model card that only describes the
|
|
384
|
+
* newest weights is the exact conflation ADR 0008 separates revisions to prevent.
|
|
385
|
+
*
|
|
386
|
+
* `license` and `provenance` are the MODEL's, repeated here rather than linked,
|
|
387
|
+
* for the same reason `modelCatalogueEntrySchema` repeats its fields: a
|
|
388
|
+
* projection that nests the operational descriptors is one accident of nesting
|
|
389
|
+
* away from serving an internal identifier.
|
|
390
|
+
*/
|
|
391
|
+
exports.modelDocumentationSchema = zod_1.z
|
|
392
|
+
.object({
|
|
393
|
+
/** See `version.ts`: this is a public response shape. */
|
|
394
|
+
schemaVersion: zod_1.z.literal(1),
|
|
395
|
+
modelId: identifiers_1.modelIdSchema,
|
|
396
|
+
revision: identifiers_1.modelRevisionLabelSchema,
|
|
397
|
+
/** The exact string a customer pins. */
|
|
398
|
+
reference: identifiers_1.modelReferenceSchema,
|
|
399
|
+
/** Whether a bare `<publisher>/<model>` resolves to this revision today. */
|
|
400
|
+
isCurrentRevision: zod_1.z.boolean(),
|
|
401
|
+
releasedAt: identifiers_1.inferenceTimestampSchema,
|
|
402
|
+
retiredAt: identifiers_1.inferenceTimestampSchema.optional(),
|
|
403
|
+
modelCardUrl: identifiers_1.inferenceHttpsUrlSchema.optional(),
|
|
404
|
+
/**
|
|
405
|
+
* The digest of the served artifact, where Oxy hosts the weights.
|
|
406
|
+
*
|
|
407
|
+
* Customer-safe, deliberately: it is the one field on this view that lets a
|
|
408
|
+
* developer check that the weights they were handed are the weights the
|
|
409
|
+
* documentation describes, and a digest discloses nothing but the identity of
|
|
410
|
+
* bytes Oxy is already serving them.
|
|
411
|
+
*/
|
|
412
|
+
artifactDigest: identifiers_1.sha256DigestSchema.optional(),
|
|
413
|
+
license: catalogue_1.modelLicenseSchema,
|
|
414
|
+
provenance: catalogue_1.modelProvenanceSchema,
|
|
415
|
+
evaluations: zod_1.z.array(catalogue_1.modelEvaluationResultSchema).default([]),
|
|
416
|
+
safety: catalogue_1.modelSafetyMetadataSchema.optional(),
|
|
417
|
+
/** Absent for a revision with no documentation record — i.e. every one Oxy did not release. */
|
|
418
|
+
gpai: exports.modelDownstreamDocumentationSchema.optional(),
|
|
419
|
+
})
|
|
420
|
+
.strict()
|
|
421
|
+
.superRefine((documentation, ctx) => {
|
|
422
|
+
// The same check `modelRevisionSchema` makes, and it is load-bearing for a
|
|
423
|
+
// different reason here: this view exists so a customer can read the
|
|
424
|
+
// documentation of the revision they PINNED, so a reference that resolves
|
|
425
|
+
// elsewhere would attach a model card to weights nobody is calling.
|
|
426
|
+
if (documentation.reference !== `${documentation.modelId}@${documentation.revision}`) {
|
|
427
|
+
ctx.addIssue({
|
|
428
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
429
|
+
path: ['reference'],
|
|
430
|
+
message: 'reference must be exactly <modelId>@<revision>',
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
});
|