@sentropic/artifacts 0.1.3 → 0.2.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/README.md +74 -4
- package/dist/adapters/postgres-commit.d.ts +15 -0
- package/dist/adapters/postgres-commit.js +80 -0
- package/dist/adapters/postgres.d.ts +5 -2
- package/dist/adapters/postgres.js +39 -0
- package/dist/content/handler.js +79 -63
- package/dist/http.d.ts +42 -29
- package/dist/http.js +168 -491
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp-core.d.ts +52 -0
- package/dist/mcp-core.js +111 -0
- package/dist/mcp.d.ts +4 -60
- package/dist/mcp.js +7 -276
- package/dist/profile/contracts.d.ts +67 -0
- package/dist/profile/contracts.js +31 -0
- package/dist/profile/index.d.ts +6 -0
- package/dist/profile/index.js +117 -0
- package/dist/profile/json.d.ts +10 -0
- package/dist/profile/json.js +76 -0
- package/dist/profile/radar.d.ts +3 -0
- package/dist/profile/radar.js +21 -0
- package/dist/profile/schemas.d.ts +6 -0
- package/dist/profile/schemas.js +76 -0
- package/dist/profile/validation.d.ts +5 -0
- package/dist/profile/validation.js +104 -0
- package/dist/profile/validators.d.ts +3 -0
- package/dist/profile/validators.js +51 -0
- package/dist/server/authorized-replay.d.ts +33 -0
- package/dist/server/authorized-replay.js +31 -0
- package/dist/server/command-identity.d.ts +52 -0
- package/dist/server/command-identity.js +71 -0
- package/dist/server/commit/brands.d.ts +7 -0
- package/dist/server/commit/brands.js +3 -0
- package/dist/server/commit/coordinator.d.ts +2 -0
- package/dist/server/commit/coordinator.js +729 -0
- package/dist/server/commit/types.d.ts +379 -0
- package/dist/server/commit/types.js +94 -0
- package/dist/server/commit-contract.d.ts +4 -0
- package/dist/server/commit-contract.js +2 -0
- package/dist/server/failures.d.ts +84 -0
- package/dist/server/failures.js +133 -0
- package/dist/server/gc.d.ts +42 -1
- package/dist/server/gc.js +168 -5
- package/dist/server/idempotency.d.ts +4 -0
- package/dist/server/idempotency.js +14 -0
- package/dist/server/lifecycle.d.ts +2 -1
- package/dist/server/lifecycle.js +15 -1
- package/dist/server/object-intents.d.ts +14 -1
- package/dist/server/object-intents.js +31 -0
- package/dist/server/outcome-contract.d.ts +3 -0
- package/dist/server/outcome-contract.js +3 -0
- package/dist/server/outcome-projection.d.ts +21 -0
- package/dist/server/outcome-projection.js +29 -0
- package/dist/server/preparation-cleanup.d.ts +31 -0
- package/dist/server/preparation-cleanup.js +106 -0
- package/dist/server/publication-limits.d.ts +10 -0
- package/dist/server/publication-limits.js +38 -0
- package/dist/server/publication.d.ts +85 -1
- package/dist/server/publication.js +288 -31
- package/dist/server/service.d.ts +64 -1
- package/dist/server/service.js +187 -1
- package/dist/server/uploads.d.ts +4 -1
- package/dist/server/uploads.js +63 -35
- package/dist/testing.d.ts +50 -0
- package/dist/testing.js +86 -0
- package/docs/migration-l6.md +129 -0
- package/examples/radar-commit-setup.ts +299 -0
- package/l0-freeze/command-identity-contract.ts +303 -0
- package/l0-freeze/commit-contract.ts +421 -0
- package/l0-freeze/failure-contract.ts +174 -0
- package/l0-freeze/profile-contract.ts +219 -0
- package/migrations/0003_coordinator.sql +28 -0
- package/package.json +31 -1
- package/src/contracts.ts +125 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Platform-free provider composition over the shared typed HTTP application. */
|
|
2
|
+
import type { AppConnectorProviderAdapter, AppMcpProviderManifest, AppToolInvocation } from '@sentropic/mcp-platform';
|
|
3
|
+
import type { ProviderParameterSchema } from '@sentropic/mcp-platform/registry';
|
|
4
|
+
import type { ArtifactApp, HttpResponse } from './http.js';
|
|
5
|
+
import { type CompiledArtifactsProfile } from './profile/index.js';
|
|
6
|
+
import type { ArtifactInvocationContext } from './server/commit/types.js';
|
|
7
|
+
import { type ArtifactOutcome } from './server/failures.js';
|
|
8
|
+
export * from './profile/index.js';
|
|
9
|
+
export { createRadarKeyDerivation } from './server/command-identity.js';
|
|
10
|
+
export type { ArtifactKeyDerivationBinding } from './server/command-identity.js';
|
|
11
|
+
export declare const ARTIFACTS_PROVIDER_ID = "sentropic.artifacts";
|
|
12
|
+
export declare const ARTIFACTS_APP_ID = "sentropic-artifacts";
|
|
13
|
+
export declare const ARTIFACTS_PROVIDER_VERSION = "0.2.0";
|
|
14
|
+
export declare const ARTIFACTS_TOOL_NAMES: readonly ["artifacts_get_template", "artifacts_get_api_guide", "artifacts_ensure", "artifacts_publish", "artifacts_create_upload", "artifacts_commit_upload", "artifacts_list", "artifacts_get", "artifacts_get_source", "artifacts_fork", "artifacts_set_access", "artifacts_promote", "artifacts_renew", "artifacts_delete", "artifacts_restore"];
|
|
15
|
+
export type ArtifactsToolName = (typeof ARTIFACTS_TOOL_NAMES)[number];
|
|
16
|
+
export declare const ARTIFACTS_TOOL_SPECS: {
|
|
17
|
+
name: "artifacts_ensure" | "artifacts_publish" | "artifacts_get_template" | "artifacts_get_api_guide" | "artifacts_create_upload" | "artifacts_commit_upload" | "artifacts_list" | "artifacts_get" | "artifacts_get_source" | "artifacts_fork" | "artifacts_set_access" | "artifacts_promote" | "artifacts_renew" | "artifacts_delete" | "artifacts_restore";
|
|
18
|
+
description: string;
|
|
19
|
+
mutability: import("@sentropic/mcp-platform").Mutability;
|
|
20
|
+
}[];
|
|
21
|
+
export declare const ARTIFACTS_PARAMETER_SCHEMA: ProviderParameterSchema;
|
|
22
|
+
export interface ArtifactsManifestOptions {
|
|
23
|
+
profile: CompiledArtifactsProfile;
|
|
24
|
+
invocationScope?: string;
|
|
25
|
+
displayName?: string;
|
|
26
|
+
}
|
|
27
|
+
export type ArtifactsManifest = AppMcpProviderManifest & {
|
|
28
|
+
audit: AppMcpProviderManifest['audit'] & {
|
|
29
|
+
artifactsProfileDigest: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export declare function createArtifactsManifest(options: ArtifactsManifestOptions): ArtifactsManifest;
|
|
33
|
+
export type ArtifactsApp = Pick<ArtifactApp, 'execute' | 'selectedCapabilities' | 'profileDigest'>;
|
|
34
|
+
export interface ArtifactsInvokeInput {
|
|
35
|
+
tool: string;
|
|
36
|
+
invocation: ArtifactInvocationContext;
|
|
37
|
+
args: unknown;
|
|
38
|
+
idempotencyKey?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function createArtifactsToolExecutor(deps: {
|
|
41
|
+
app: ArtifactsApp;
|
|
42
|
+
profile: CompiledArtifactsProfile;
|
|
43
|
+
}): {
|
|
44
|
+
execute: (input: ArtifactsInvokeInput) => Promise<ArtifactOutcome<HttpResponse>>;
|
|
45
|
+
invoke(input: ArtifactsInvokeInput): Promise<HttpResponse>;
|
|
46
|
+
};
|
|
47
|
+
export interface ArtifactsAdapterOptions extends ArtifactsManifestOptions {
|
|
48
|
+
app: ArtifactsApp;
|
|
49
|
+
/** Bind verified principal/scope and request authorization in trusted host code. */
|
|
50
|
+
createInvocation(request: AppToolInvocation): ArtifactInvocationContext | Promise<ArtifactInvocationContext>;
|
|
51
|
+
}
|
|
52
|
+
export declare function createArtifactsAdapter(options: ArtifactsAdapterOptions): AppConnectorProviderAdapter;
|
package/dist/mcp-core.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { assertArtifactsTransportProfile } from './http.js';
|
|
2
|
+
import { ARTIFACT_CAPABILITY_NAMES, ArtifactProfileInputError } from './profile/index.js';
|
|
3
|
+
import { ArtifactOperationError, classifyArtifactFailure } from './server/failures.js';
|
|
4
|
+
import { projectArtifactHttpOutcome, projectArtifactMcpOutcome } from './server/outcome-projection.js';
|
|
5
|
+
export * from './profile/index.js';
|
|
6
|
+
export { createRadarKeyDerivation } from './server/command-identity.js';
|
|
7
|
+
export const ARTIFACTS_PROVIDER_ID = 'sentropic.artifacts';
|
|
8
|
+
export const ARTIFACTS_APP_ID = 'sentropic-artifacts';
|
|
9
|
+
export const ARTIFACTS_PROVIDER_VERSION = '0.2.0';
|
|
10
|
+
export const ARTIFACTS_TOOL_NAMES = ARTIFACT_CAPABILITY_NAMES;
|
|
11
|
+
export const ARTIFACTS_TOOL_SPECS = ARTIFACTS_TOOL_NAMES.map((name) => ({ name,
|
|
12
|
+
description: `Artifacts ${name.slice('artifacts_'.length).replaceAll('_', ' ')}.`,
|
|
13
|
+
mutability: (['artifacts_list', 'artifacts_get', 'artifacts_get_template', 'artifacts_get_api_guide',
|
|
14
|
+
'artifacts_get_source'].includes(name) ? 'read-only' : name === 'artifacts_publish' ? 'append' : 'state-transition'),
|
|
15
|
+
}));
|
|
16
|
+
export const ARTIFACTS_PARAMETER_SCHEMA = { properties: {}, required: [] };
|
|
17
|
+
export function createArtifactsManifest(options) {
|
|
18
|
+
assertArtifactsTransportProfile(options?.profile);
|
|
19
|
+
const { profile } = options;
|
|
20
|
+
const scopes = options.invocationScope === undefined ? [] : [options.invocationScope];
|
|
21
|
+
return {
|
|
22
|
+
appId: ARTIFACTS_APP_ID, providerId: ARTIFACTS_PROVIDER_ID, version: ARTIFACTS_PROVIDER_VERSION,
|
|
23
|
+
displayName: options.displayName ?? 'Sentropic Artifacts',
|
|
24
|
+
resources: [], prompts: [],
|
|
25
|
+
tools: ARTIFACTS_TOOL_SPECS.filter((spec) => profile.selectedCapabilities.includes(spec.name)).map((spec) => ({
|
|
26
|
+
kind: 'tool', name: spec.name,
|
|
27
|
+
description: spec.description,
|
|
28
|
+
inputSchema: profile.schemas[spec.name], outputSchema: { type: 'object' },
|
|
29
|
+
requiredScopes: [...scopes], requiredClaims: [], redactionClass: 'low',
|
|
30
|
+
mutability: spec.mutability, mutatesExternalSystem: spec.mutability !== 'read-only',
|
|
31
|
+
idempotency: profile.idempotency[spec.name] ?? { required: false },
|
|
32
|
+
gates: { requiresElicitation: false, requiresHumanConfirmation: false, requiresPrincipalGate: false },
|
|
33
|
+
})),
|
|
34
|
+
authz: { requiredClaims: [], scopes, tenantResolution: 'custom-resolver' },
|
|
35
|
+
// The existing manifest codec includes audit metadata, including for an empty tool set.
|
|
36
|
+
audit: { eventKinds: ['invoke'], artifactsProfileDigest: profile.profileDigest }, durability: {},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function rejected(cause, invocationId, operation) {
|
|
40
|
+
return { ok: false, failure: classifyArtifactFailure(cause, { invocationId, operation,
|
|
41
|
+
phase: cause instanceof ArtifactProfileInputError ? cause.phase : 'entry', commitState: 'not_committed' }, (error) => error instanceof ArtifactProfileInputError ? new ArtifactOperationError(error.category) : undefined) };
|
|
42
|
+
}
|
|
43
|
+
export function createArtifactsToolExecutor(deps) {
|
|
44
|
+
assertArtifactsTransportProfile(deps.profile);
|
|
45
|
+
const profile = deps.profile;
|
|
46
|
+
if (deps.app.profileDigest !== profile.profileDigest ||
|
|
47
|
+
JSON.stringify(deps.app.selectedCapabilities) !== JSON.stringify(profile.selectedCapabilities)) {
|
|
48
|
+
throw new Error('artifacts app/profile mismatch');
|
|
49
|
+
}
|
|
50
|
+
async function execute(input) {
|
|
51
|
+
try {
|
|
52
|
+
const args = profile.validate(input.tool, input.args, input.idempotencyKey);
|
|
53
|
+
let request;
|
|
54
|
+
switch (input.tool) {
|
|
55
|
+
case 'artifacts_ensure':
|
|
56
|
+
request = { method: 'POST', path: '/ensure', body: args };
|
|
57
|
+
break;
|
|
58
|
+
case 'artifacts_publish':
|
|
59
|
+
request = { method: 'POST', path: '/publish', body: args };
|
|
60
|
+
break;
|
|
61
|
+
case 'artifacts_list':
|
|
62
|
+
request = { method: 'POST', path: '/list', body: args };
|
|
63
|
+
break;
|
|
64
|
+
case 'artifacts_get':
|
|
65
|
+
request = { method: 'GET', path: `/meta/${args.artifactId}`, body: undefined };
|
|
66
|
+
break;
|
|
67
|
+
default: throw new ArtifactProfileInputError(true);
|
|
68
|
+
}
|
|
69
|
+
return await deps.app.execute({ ...request, actorId: input.invocation.actorId,
|
|
70
|
+
storageScopeId: input.invocation.storageScopeId, idempotencyKey: input.idempotencyKey }, input.invocation);
|
|
71
|
+
}
|
|
72
|
+
catch (cause) {
|
|
73
|
+
return rejected(cause, input.invocation?.invocationId ?? '', input.tool);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { execute, async invoke(input) {
|
|
77
|
+
return projectArtifactHttpOutcome(await execute(input));
|
|
78
|
+
} };
|
|
79
|
+
}
|
|
80
|
+
export function createArtifactsAdapter(options) {
|
|
81
|
+
const manifest = createArtifactsManifest(options);
|
|
82
|
+
if (typeof options.createInvocation !== 'function')
|
|
83
|
+
throw new Error('artifacts requires a trusted invocation factory');
|
|
84
|
+
const executor = createArtifactsToolExecutor(options);
|
|
85
|
+
return {
|
|
86
|
+
appId: ARTIFACTS_APP_ID, connectorId: ARTIFACTS_PROVIDER_ID, manifest,
|
|
87
|
+
resolveTenant: async (input) => ({ principalRef: input.principalSub, tenantRef: input.tenantRef,
|
|
88
|
+
connectorInstanceId: input.connectorInstanceId,
|
|
89
|
+
...(input.workspaceRef === undefined ? {} : { workspaceRef: input.workspaceRef }) }),
|
|
90
|
+
listCapabilities: async () => [...manifest.tools],
|
|
91
|
+
async invokeTool(request) {
|
|
92
|
+
let outcome;
|
|
93
|
+
try {
|
|
94
|
+
// Selection and closed input checks precede even the host invocation binding.
|
|
95
|
+
options.profile.validate(request.capabilityRef, request.input, request.idempotencyKey);
|
|
96
|
+
const invocation = await options.createInvocation(request);
|
|
97
|
+
if (invocation.actorId !== request.ctx.principal.sub)
|
|
98
|
+
throw new ArtifactProfileInputError();
|
|
99
|
+
outcome = await executor.execute({ tool: request.capabilityRef, args: request.input,
|
|
100
|
+
invocation, idempotencyKey: request.idempotencyKey });
|
|
101
|
+
}
|
|
102
|
+
catch (cause) {
|
|
103
|
+
outcome = rejected(cause, request.ctx.requestId, request.capabilityRef);
|
|
104
|
+
}
|
|
105
|
+
return projectArtifactMcpOutcome(outcome, request.ctx.auditId);
|
|
106
|
+
},
|
|
107
|
+
readResource: async (request) => ({ ok: false, auditId: request.ctx.auditId, redactionClass: 'low',
|
|
108
|
+
error: { code: 'not_found', message: 'not_found', retriable: false } }),
|
|
109
|
+
validateSecrets: async () => [],
|
|
110
|
+
};
|
|
111
|
+
}
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,62 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* schemas, and the platform manifest. The logical provider ID is
|
|
6
|
-
* `sentropic.artifacts`; the generic provider hardcodes no application
|
|
7
|
-
* OAuth vocabulary — a host binds its invocation scope through the
|
|
8
|
-
* manifest factory before digests freeze (§3.5). Part 2 adds the tool
|
|
9
|
-
* executor over the same HTTP app direct calls use; part 3 adds the
|
|
10
|
-
* platform adapter and the kernel registry definition (§3).
|
|
11
|
-
*/
|
|
12
|
-
import type { AppConnectorProviderAdapter, AppMcpProviderManifest, CapabilityTool } from '@sentropic/mcp-platform';
|
|
13
|
-
import type { ProviderParameterSchema, RegistryDefinition } from '@sentropic/mcp-platform/registry';
|
|
14
|
-
import type { HttpRequest, HttpResponse } from './http.js';
|
|
15
|
-
export declare const ARTIFACTS_PROVIDER_ID = "sentropic.artifacts";
|
|
16
|
-
export declare const ARTIFACTS_APP_ID = "sentropic-artifacts";
|
|
17
|
-
export declare const ARTIFACTS_PROVIDER_VERSION = "0.1.2";
|
|
18
|
-
export declare const ARTIFACTS_TOOL_NAMES: readonly ["artifacts_get_template", "artifacts_get_api_guide", "artifacts_ensure", "artifacts_publish", "artifacts_create_upload", "artifacts_commit_upload", "artifacts_list", "artifacts_get", "artifacts_get_source", "artifacts_fork", "artifacts_set_access", "artifacts_promote", "artifacts_renew", "artifacts_delete", "artifacts_restore"];
|
|
19
|
-
export type ArtifactsToolName = (typeof ARTIFACTS_TOOL_NAMES)[number];
|
|
20
|
-
type Schema = Record<string, unknown>;
|
|
21
|
-
interface ToolSpec {
|
|
22
|
-
name: ArtifactsToolName;
|
|
23
|
-
description: string;
|
|
24
|
-
inputSchema: Schema;
|
|
25
|
-
mutability: CapabilityTool['mutability'];
|
|
26
|
-
idempotent?: boolean;
|
|
27
|
-
confirm?: boolean;
|
|
28
|
-
}
|
|
29
|
-
export declare const ARTIFACTS_TOOL_SPECS: readonly ToolSpec[];
|
|
30
|
-
/** Kernel provider parameter schema (typed non-secret host settings). */
|
|
31
|
-
export declare const ARTIFACTS_PARAMETER_SCHEMA: ProviderParameterSchema;
|
|
32
|
-
export interface ArtifactsManifestOptions {
|
|
33
|
-
/** Host authorization profile: scope bound to every tool invocation. */
|
|
34
|
-
invocationScope?: string;
|
|
35
|
-
displayName?: string;
|
|
36
|
-
}
|
|
37
|
-
/** Build the sentropic.artifacts manifest (host scope bound pre-freeze). */
|
|
38
|
-
export declare function createArtifactsManifest(options?: ArtifactsManifestOptions): AppMcpProviderManifest;
|
|
39
|
-
export interface ArtifactsApp {
|
|
40
|
-
handle(request: HttpRequest): Promise<HttpResponse>;
|
|
41
|
-
}
|
|
42
|
-
export interface ArtifactsInvokeInput {
|
|
43
|
-
tool: string;
|
|
44
|
-
actorId: string;
|
|
45
|
-
args: Record<string, unknown>;
|
|
46
|
-
}
|
|
47
|
-
/** Create the 15-tool executor over any conforming artifacts HTTP app. */
|
|
48
|
-
export declare function createArtifactsToolExecutor(deps: {
|
|
49
|
-
app: ArtifactsApp;
|
|
50
|
-
defaultStorageScopeId?: string;
|
|
51
|
-
}): {
|
|
52
|
-
invoke(input: ArtifactsInvokeInput): Promise<HttpResponse>;
|
|
53
|
-
};
|
|
54
|
-
export interface ArtifactsAdapterOptions extends ArtifactsManifestOptions {
|
|
55
|
-
app: ArtifactsApp;
|
|
56
|
-
defaultStorageScopeId?: string;
|
|
57
|
-
}
|
|
58
|
-
/** Create the platform adapter driving the 15 tools over the shared app. */
|
|
59
|
-
export declare function createArtifactsAdapter(options: ArtifactsAdapterOptions): AppConnectorProviderAdapter;
|
|
1
|
+
/** Platform registry wrapper. Use /mcp-core when the platform is absent. */
|
|
2
|
+
export * from './mcp-core.js';
|
|
3
|
+
import type { RegistryDefinition } from '@sentropic/mcp-platform/registry';
|
|
4
|
+
import { type ArtifactsAdapterOptions } from './mcp-core.js';
|
|
60
5
|
export interface ArtifactsDefinitionOptions extends ArtifactsAdapterOptions {
|
|
61
6
|
/** Local config-review reference (integrity metadata, never authority). */
|
|
62
7
|
approvalRef?: string;
|
|
@@ -65,4 +10,3 @@ export interface ArtifactsDefinitionOptions extends ArtifactsAdapterOptions {
|
|
|
65
10
|
}
|
|
66
11
|
/** Build the kernel registry definition for sentropic.artifacts (§3). */
|
|
67
12
|
export declare function createArtifactsRegistryDefinition(options: ArtifactsDefinitionOptions): RegistryDefinition;
|
|
68
|
-
export {};
|
package/dist/mcp.js
CHANGED
|
@@ -1,276 +1,7 @@
|
|
|
1
|
+
/** Platform registry wrapper. Use /mcp-core when the platform is absent. */
|
|
2
|
+
export * from './mcp-core.js';
|
|
1
3
|
import { computeManifestDigest } from '@sentropic/mcp-platform/tool-configuration';
|
|
2
|
-
import {
|
|
3
|
-
export const ARTIFACTS_PROVIDER_ID = 'sentropic.artifacts';
|
|
4
|
-
export const ARTIFACTS_APP_ID = 'sentropic-artifacts';
|
|
5
|
-
export const ARTIFACTS_PROVIDER_VERSION = '0.1.2';
|
|
6
|
-
export const ARTIFACTS_TOOL_NAMES = [
|
|
7
|
-
'artifacts_get_template', 'artifacts_get_api_guide', 'artifacts_ensure',
|
|
8
|
-
'artifacts_publish', 'artifacts_create_upload', 'artifacts_commit_upload',
|
|
9
|
-
'artifacts_list', 'artifacts_get', 'artifacts_get_source', 'artifacts_fork',
|
|
10
|
-
'artifacts_set_access', 'artifacts_promote', 'artifacts_renew',
|
|
11
|
-
'artifacts_delete', 'artifacts_restore',
|
|
12
|
-
];
|
|
13
|
-
const str = { type: 'string', minLength: 1 };
|
|
14
|
-
const int = (minimum, maximum) => ({
|
|
15
|
-
type: 'integer', minimum, ...(maximum === undefined ? {} : { maximum }),
|
|
16
|
-
});
|
|
17
|
-
const obj = (properties, required = []) => ({
|
|
18
|
-
type: 'object', properties, required, additionalProperties: false,
|
|
19
|
-
});
|
|
20
|
-
const record = {
|
|
21
|
-
type: 'object',
|
|
22
|
-
additionalProperties: { type: ['string', 'number', 'boolean', 'null'] },
|
|
23
|
-
};
|
|
24
|
-
const fileBytes = { type: 'array', items: int(0, 255) };
|
|
25
|
-
const fileEntry = {
|
|
26
|
-
...obj({ path: str, mimeType: str, bytes: fileBytes, text: { type: 'string', description: 'UTF-8 text; mutually exclusive with bytes; text MIME types only.' } }, ['path', 'mimeType']),
|
|
27
|
-
oneOf: [
|
|
28
|
-
{ required: ['bytes'], not: { required: ['text'] } },
|
|
29
|
-
{ required: ['text'], not: { required: ['bytes'] }, properties: { mimeType: { pattern: TEXT_MIME_PATTERN } } },
|
|
30
|
-
],
|
|
31
|
-
};
|
|
32
|
-
const sourceRef = obj({
|
|
33
|
-
kind: { type: 'string', enum: ['inline-original', 'base-commit', 'recipe'] },
|
|
34
|
-
commit: { type: 'string' },
|
|
35
|
-
steps: { type: 'array', items: { type: 'string' } },
|
|
36
|
-
}, ['kind']);
|
|
37
|
-
const idOnly = obj({ artifactId: str }, ['artifactId']);
|
|
38
|
-
export const ARTIFACTS_TOOL_SPECS = [
|
|
39
|
-
{ name: 'artifacts_get_template', description: 'Get an approved template kit (sources + build recipe).', inputSchema: obj({ templateId: str }, ['templateId']), mutability: 'read-only' },
|
|
40
|
-
{ name: 'artifacts_get_api_guide', description: 'Get the versioned artifacts API guide.', inputSchema: obj({ version: str }), mutability: 'read-only' },
|
|
41
|
-
{ name: 'artifacts_ensure', description: 'Resolve or create the private artifact view for a binding.', inputSchema: obj({ bindingName: str, storageScopeId: str, idempotencyKey: str, paramsHash: str, parameters: record }, ['bindingName', 'idempotencyKey']), mutability: 'state-transition', idempotent: true },
|
|
42
|
-
{ name: 'artifacts_publish', description: 'Publish inline files as a new release.', inputSchema: obj({ artifactId: str, files: { type: 'array', minItems: 1, items: fileEntry }, profile: record, source: sourceRef, idempotencyKey: str, paramsHash: str }, ['artifactId', 'files']), mutability: 'append', idempotent: true },
|
|
43
|
-
{ name: 'artifacts_create_upload', description: 'Open a bounded upload session for large bytes.', inputSchema: obj({ artifactId: str, mimeType: str, maxSize: int(1) }, ['artifactId', 'mimeType']), mutability: 'state-transition' },
|
|
44
|
-
{ name: 'artifacts_commit_upload', description: 'Verify staged bytes and publish them as a release.', inputSchema: obj({ artifactId: str, uploadId: str, path: str, mimeType: str, digest: str, size: int(0), profile: record, idempotencyKey: str, paramsHash: str }, ['artifactId', 'uploadId', 'path', 'mimeType', 'digest', 'size']), mutability: 'append', idempotent: true },
|
|
45
|
-
{ name: 'artifacts_list', description: 'List artifacts visible to the caller (ACL before pagination).', inputSchema: obj({ limit: int(1, 100), offset: int(0) }), mutability: 'read-only' },
|
|
46
|
-
{ name: 'artifacts_get', description: 'Get artifact metadata (grants visible to the owner only).', inputSchema: idOnly, mutability: 'read-only' },
|
|
47
|
-
{ name: 'artifacts_get_source', description: 'Export the attached source reference (separate right).', inputSchema: idOnly, mutability: 'read-only' },
|
|
48
|
-
{ name: 'artifacts_fork', description: 'Fork privately under a fresh identity (no ACL copied).', inputSchema: idOnly, mutability: 'state-transition' },
|
|
49
|
-
{ name: 'artifacts_set_access', description: 'Grant or revoke read/source access, or toggle public mode.', inputSchema: obj({ artifactId: str, action: { type: 'string', enum: ['grant', 'revoke', 'set-public'] }, principalId: str, grant: { type: 'string', enum: ['read', 'source'] }, isPublic: { type: 'boolean' } }, ['artifactId', 'action']), mutability: 'patch', confirm: true },
|
|
50
|
-
{ name: 'artifacts_promote', description: 'Select a release explicitly (expected-current CAS).', inputSchema: obj({ artifactId: str, releaseId: str, expectedCurrent: str }, ['artifactId', 'releaseId', 'expectedCurrent']), mutability: 'patch' },
|
|
51
|
-
{ name: 'artifacts_renew', description: 'Renew the artifact retention timestamp.', inputSchema: idOnly, mutability: 'patch' },
|
|
52
|
-
{ name: 'artifacts_delete', description: 'Withdraw into pending deletion (undo via artifacts_restore).', inputSchema: idOnly, mutability: 'delete', confirm: true },
|
|
53
|
-
{ name: 'artifacts_restore', description: 'Cancel a pending deletion or withdrawal before purge.', inputSchema: idOnly, mutability: 'state-transition' },
|
|
54
|
-
];
|
|
55
|
-
/** Kernel provider parameter schema (typed non-secret host settings). */
|
|
56
|
-
export const ARTIFACTS_PARAMETER_SCHEMA = {
|
|
57
|
-
properties: {
|
|
58
|
-
defaultStorageScopeId: { type: 'string', minLength: 1, description: 'Fallback storage scope for artifacts_ensure.' },
|
|
59
|
-
uploadBudgetBytes: { type: 'integer', minimum: 1, description: 'Declared bounded-upload budget.' },
|
|
60
|
-
},
|
|
61
|
-
required: [],
|
|
62
|
-
};
|
|
63
|
-
/** Build the sentropic.artifacts manifest (host scope bound pre-freeze). */
|
|
64
|
-
export function createArtifactsManifest(options = {}) {
|
|
65
|
-
const scopes = options.invocationScope === undefined ? [] : [options.invocationScope];
|
|
66
|
-
const tools = ARTIFACTS_TOOL_SPECS.map((spec) => ({
|
|
67
|
-
kind: 'tool',
|
|
68
|
-
name: spec.name,
|
|
69
|
-
description: spec.description,
|
|
70
|
-
requiredScopes: [...scopes],
|
|
71
|
-
requiredClaims: [],
|
|
72
|
-
inputSchema: spec.inputSchema,
|
|
73
|
-
outputSchema: { type: 'object' },
|
|
74
|
-
redactionClass: 'low',
|
|
75
|
-
mutability: spec.mutability,
|
|
76
|
-
mutatesExternalSystem: spec.mutability !== 'read-only',
|
|
77
|
-
idempotency: spec.idempotent === true
|
|
78
|
-
? { required: true, scope: 'principal' }
|
|
79
|
-
: { required: false },
|
|
80
|
-
gates: {
|
|
81
|
-
requiresElicitation: false,
|
|
82
|
-
requiresHumanConfirmation: spec.confirm === true,
|
|
83
|
-
requiresPrincipalGate: false,
|
|
84
|
-
},
|
|
85
|
-
}));
|
|
86
|
-
return {
|
|
87
|
-
appId: ARTIFACTS_APP_ID,
|
|
88
|
-
providerId: ARTIFACTS_PROVIDER_ID,
|
|
89
|
-
version: ARTIFACTS_PROVIDER_VERSION,
|
|
90
|
-
displayName: options.displayName ?? 'Sentropic Artifacts',
|
|
91
|
-
resources: [],
|
|
92
|
-
tools,
|
|
93
|
-
prompts: [],
|
|
94
|
-
authz: { requiredClaims: [], scopes: [...scopes], tenantResolution: 'custom-resolver' },
|
|
95
|
-
audit: { eventKinds: ['invoke'] },
|
|
96
|
-
durability: {},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
function needString(args, name) {
|
|
100
|
-
const value = args[name];
|
|
101
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
102
|
-
throw new Error(`invalid request: missing ${name}`);
|
|
103
|
-
}
|
|
104
|
-
return value;
|
|
105
|
-
}
|
|
106
|
-
function optString(args, name) {
|
|
107
|
-
const value = args[name];
|
|
108
|
-
return typeof value === 'string' && value.length !== 0 ? value : undefined;
|
|
109
|
-
}
|
|
110
|
-
/** Create the 15-tool executor over any conforming artifacts HTTP app. */
|
|
111
|
-
export function createArtifactsToolExecutor(deps) {
|
|
112
|
-
const call = (actorId, method, path, body) => deps.app.handle({ method, path, actorId, body });
|
|
113
|
-
function setAccess(actorId, args) {
|
|
114
|
-
const artifactId = needString(args, 'artifactId');
|
|
115
|
-
const action = needString(args, 'action');
|
|
116
|
-
if (action === 'grant') {
|
|
117
|
-
const grant = needString(args, 'grant');
|
|
118
|
-
if (grant !== 'read' && grant !== 'source') {
|
|
119
|
-
throw new Error('invalid request: grant must be read or source');
|
|
120
|
-
}
|
|
121
|
-
return call(actorId, 'POST', '/access/grant', {
|
|
122
|
-
artifactId, principalId: needString(args, 'principalId'), grant,
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
if (action === 'revoke') {
|
|
126
|
-
return call(actorId, 'POST', '/access/revoke', {
|
|
127
|
-
artifactId, principalId: needString(args, 'principalId'),
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
if (action === 'set-public') {
|
|
131
|
-
if (typeof args['isPublic'] !== 'boolean') {
|
|
132
|
-
throw new Error('invalid request: isPublic must be a boolean');
|
|
133
|
-
}
|
|
134
|
-
return call(actorId, 'POST', '/access/public', { artifactId, isPublic: args['isPublic'] });
|
|
135
|
-
}
|
|
136
|
-
throw new Error(`invalid request: unknown set-access action ${action}`);
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
async invoke(input) {
|
|
140
|
-
const { actorId, args } = input;
|
|
141
|
-
switch (input.tool) {
|
|
142
|
-
case 'artifacts_get_template':
|
|
143
|
-
return call(actorId, 'GET', `/templates/${needString(args, 'templateId')}`);
|
|
144
|
-
case 'artifacts_get_api_guide': {
|
|
145
|
-
const version = optString(args, 'version');
|
|
146
|
-
return call(actorId, 'GET', version === undefined ? '/api-guide' : `/api-guide/${version}`);
|
|
147
|
-
}
|
|
148
|
-
case 'artifacts_ensure':
|
|
149
|
-
return call(actorId, 'POST', '/ensure', {
|
|
150
|
-
bindingName: needString(args, 'bindingName'),
|
|
151
|
-
storageScopeId: optString(args, 'storageScopeId') ?? deps.defaultStorageScopeId
|
|
152
|
-
?? needString(args, 'storageScopeId'),
|
|
153
|
-
idempotencyKey: needString(args, 'idempotencyKey'),
|
|
154
|
-
paramsHash: optString(args, 'paramsHash') ?? '',
|
|
155
|
-
parameters: args['parameters'] ?? {},
|
|
156
|
-
});
|
|
157
|
-
case 'artifacts_publish':
|
|
158
|
-
return call(actorId, 'POST', '/publish', {
|
|
159
|
-
artifactId: needString(args, 'artifactId'),
|
|
160
|
-
files: args['files'],
|
|
161
|
-
profile: args['profile'] ?? {},
|
|
162
|
-
source: args['source'],
|
|
163
|
-
idempotencyKey: optString(args, 'idempotencyKey'),
|
|
164
|
-
paramsHash: optString(args, 'paramsHash'),
|
|
165
|
-
});
|
|
166
|
-
case 'artifacts_create_upload':
|
|
167
|
-
return call(actorId, 'POST', '/uploads', {
|
|
168
|
-
artifactId: needString(args, 'artifactId'),
|
|
169
|
-
mimeType: needString(args, 'mimeType'),
|
|
170
|
-
maxSize: args['maxSize'],
|
|
171
|
-
});
|
|
172
|
-
case 'artifacts_commit_upload':
|
|
173
|
-
return call(actorId, 'POST', '/uploads/commit', {
|
|
174
|
-
artifactId: needString(args, 'artifactId'),
|
|
175
|
-
uploadId: needString(args, 'uploadId'),
|
|
176
|
-
path: needString(args, 'path'),
|
|
177
|
-
mimeType: needString(args, 'mimeType'),
|
|
178
|
-
digest: needString(args, 'digest'),
|
|
179
|
-
size: args['size'],
|
|
180
|
-
profile: args['profile'] ?? {},
|
|
181
|
-
idempotencyKey: optString(args, 'idempotencyKey'),
|
|
182
|
-
paramsHash: optString(args, 'paramsHash'),
|
|
183
|
-
});
|
|
184
|
-
case 'artifacts_list':
|
|
185
|
-
return call(actorId, 'POST', '/list', { limit: args['limit'], offset: args['offset'] });
|
|
186
|
-
case 'artifacts_get':
|
|
187
|
-
return call(actorId, 'GET', `/meta/${needString(args, 'artifactId')}`);
|
|
188
|
-
case 'artifacts_get_source':
|
|
189
|
-
return call(actorId, 'GET', `/source/${needString(args, 'artifactId')}`);
|
|
190
|
-
case 'artifacts_fork':
|
|
191
|
-
return call(actorId, 'POST', '/fork', { artifactId: needString(args, 'artifactId') });
|
|
192
|
-
case 'artifacts_set_access':
|
|
193
|
-
return setAccess(actorId, args);
|
|
194
|
-
case 'artifacts_promote':
|
|
195
|
-
return call(actorId, 'POST', '/promote', {
|
|
196
|
-
artifactId: needString(args, 'artifactId'),
|
|
197
|
-
releaseId: needString(args, 'releaseId'),
|
|
198
|
-
expectedCurrent: needString(args, 'expectedCurrent'),
|
|
199
|
-
});
|
|
200
|
-
case 'artifacts_renew':
|
|
201
|
-
return call(actorId, 'POST', '/renew', { artifactId: needString(args, 'artifactId') });
|
|
202
|
-
case 'artifacts_delete':
|
|
203
|
-
return call(actorId, 'POST', '/delete', { artifactId: needString(args, 'artifactId') });
|
|
204
|
-
case 'artifacts_restore':
|
|
205
|
-
return call(actorId, 'POST', '/restore', { artifactId: needString(args, 'artifactId') });
|
|
206
|
-
default:
|
|
207
|
-
throw new Error(`unknown artifacts tool: ${input.tool}`);
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
function errorCodeOf(body) {
|
|
213
|
-
if (typeof body === 'object' && body !== null) {
|
|
214
|
-
const code = body['error'];
|
|
215
|
-
if (typeof code === 'string' && code.length !== 0)
|
|
216
|
-
return code;
|
|
217
|
-
}
|
|
218
|
-
return 'internal_error';
|
|
219
|
-
}
|
|
220
|
-
/** Create the platform adapter driving the 15 tools over the shared app. */
|
|
221
|
-
export function createArtifactsAdapter(options) {
|
|
222
|
-
const manifest = createArtifactsManifest(options);
|
|
223
|
-
const executor = createArtifactsToolExecutor({
|
|
224
|
-
app: options.app,
|
|
225
|
-
defaultStorageScopeId: options.defaultStorageScopeId,
|
|
226
|
-
});
|
|
227
|
-
return {
|
|
228
|
-
appId: ARTIFACTS_APP_ID,
|
|
229
|
-
connectorId: ARTIFACTS_PROVIDER_ID,
|
|
230
|
-
manifest,
|
|
231
|
-
resolveTenant: (input) => Promise.resolve({
|
|
232
|
-
principalRef: input.principalSub,
|
|
233
|
-
tenantRef: input.tenantRef,
|
|
234
|
-
connectorInstanceId: input.connectorInstanceId,
|
|
235
|
-
...(input.workspaceRef === undefined ? {} : { workspaceRef: input.workspaceRef }),
|
|
236
|
-
}),
|
|
237
|
-
listCapabilities: () => Promise.resolve([...manifest.tools]),
|
|
238
|
-
async invokeTool(req) {
|
|
239
|
-
const auditId = req.ctx.auditId;
|
|
240
|
-
try {
|
|
241
|
-
const args = typeof req.input === 'object' && req.input !== null && !Array.isArray(req.input)
|
|
242
|
-
? req.input
|
|
243
|
-
: {};
|
|
244
|
-
const res = await executor.invoke({
|
|
245
|
-
tool: req.capabilityRef,
|
|
246
|
-
actorId: req.ctx.principal.sub,
|
|
247
|
-
args,
|
|
248
|
-
});
|
|
249
|
-
if (res.status >= 200 && res.status < 300) {
|
|
250
|
-
return { ok: true, output: res.body, auditId, redactionClass: 'low' };
|
|
251
|
-
}
|
|
252
|
-
const code = errorCodeOf(res.body);
|
|
253
|
-
return {
|
|
254
|
-
ok: false, auditId, redactionClass: 'low',
|
|
255
|
-
error: { code, message: code, retriable: res.status >= 500 },
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
return {
|
|
260
|
-
ok: false, auditId, redactionClass: 'low',
|
|
261
|
-
error: { code: 'invalid_request', message: 'invalid_request', retriable: false },
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
},
|
|
265
|
-
readResource: (req) => Promise.resolve({
|
|
266
|
-
ok: false,
|
|
267
|
-
auditId: req.ctx.auditId,
|
|
268
|
-
redactionClass: 'low',
|
|
269
|
-
error: { code: 'not_found', message: 'not_found', retriable: false },
|
|
270
|
-
}),
|
|
271
|
-
validateSecrets: () => Promise.resolve([]),
|
|
272
|
-
};
|
|
273
|
-
}
|
|
4
|
+
import { createArtifactsAdapter, ARTIFACTS_PARAMETER_SCHEMA, } from './mcp-core.js';
|
|
274
5
|
const EMPTY_TOOL_CONFIG = { type: 'object', properties: {}, additionalProperties: false };
|
|
275
6
|
/** Build the kernel registry definition for sentropic.artifacts (§3). */
|
|
276
7
|
export function createArtifactsRegistryDefinition(options) {
|
|
@@ -278,10 +9,10 @@ export function createArtifactsRegistryDefinition(options) {
|
|
|
278
9
|
const manifest = adapter.manifest;
|
|
279
10
|
const handlers = {};
|
|
280
11
|
const toolValues = {};
|
|
281
|
-
for (const
|
|
282
|
-
const handlerId = `${
|
|
283
|
-
handlers[handlerId] = { handlerId, capabilityRef:
|
|
284
|
-
toolValues[
|
|
12
|
+
for (const tool of manifest.tools) {
|
|
13
|
+
const handlerId = `${tool.name}-handler`;
|
|
14
|
+
handlers[handlerId] = { handlerId, capabilityRef: tool.name, configSchema: EMPTY_TOOL_CONFIG };
|
|
15
|
+
toolValues[tool.name] = { handlerId, values: {} };
|
|
285
16
|
}
|
|
286
17
|
return {
|
|
287
18
|
manifest,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { JsonValue } from '../contracts.js';
|
|
2
|
+
import type { EffectiveArtifactCommand } from '../server/command-identity.js';
|
|
3
|
+
export declare const PROFILE_CONTRACT_VERSION: "artifacts-profile/v1";
|
|
4
|
+
export declare const ARTIFACT_CAPABILITY_NAMES: readonly ["artifacts_get_template", "artifacts_get_api_guide", "artifacts_ensure", "artifacts_publish", "artifacts_create_upload", "artifacts_commit_upload", "artifacts_list", "artifacts_get", "artifacts_get_source", "artifacts_fork", "artifacts_set_access", "artifacts_promote", "artifacts_renew", "artifacts_delete", "artifacts_restore"];
|
|
5
|
+
export type ArtifactCapabilityName = (typeof ARTIFACT_CAPABILITY_NAMES)[number];
|
|
6
|
+
export type ArtifactSchema = Readonly<Record<string, unknown>>;
|
|
7
|
+
export interface OperationProfile {
|
|
8
|
+
readonly operation: string;
|
|
9
|
+
readonly limits: Record<string, number>;
|
|
10
|
+
readonly defaults: Record<string, JsonValue | undefined>;
|
|
11
|
+
}
|
|
12
|
+
export interface ArtifactProfileRules {
|
|
13
|
+
readonly lengthUnit: 'utf16';
|
|
14
|
+
readonly textEncoding: 'utf8';
|
|
15
|
+
readonly callerKeyNormalization: 'none';
|
|
16
|
+
readonly rejectLoneSurrogates: true;
|
|
17
|
+
readonly provenance: 'inline-original';
|
|
18
|
+
readonly keyDerivationAlgorithm: string;
|
|
19
|
+
readonly pathMaxBytes: number;
|
|
20
|
+
readonly forbiddenPathPattern: string;
|
|
21
|
+
readonly reservedFirstSegments: readonly string[];
|
|
22
|
+
readonly mimeTypes: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export interface ArtifactProviderProfile {
|
|
25
|
+
readonly version: typeof PROFILE_CONTRACT_VERSION;
|
|
26
|
+
readonly selectedCapabilities: readonly string[];
|
|
27
|
+
readonly operations: readonly OperationProfile[];
|
|
28
|
+
readonly contractRevisions: Record<string, string>;
|
|
29
|
+
/** Omission selects the fixed v1 semantics, never a capability selection. */
|
|
30
|
+
readonly rules?: ArtifactProfileRules;
|
|
31
|
+
}
|
|
32
|
+
export interface EffectiveArtifactProfile extends ArtifactProviderProfile {
|
|
33
|
+
readonly rules: ArtifactProfileRules;
|
|
34
|
+
}
|
|
35
|
+
export interface CompiledArtifactsProfile extends EffectiveArtifactProfile {
|
|
36
|
+
readonly selectedCapabilities: readonly ArtifactCapabilityName[];
|
|
37
|
+
readonly profile: EffectiveArtifactProfile;
|
|
38
|
+
readonly profileDigest: string;
|
|
39
|
+
readonly validators: CompiledValidators;
|
|
40
|
+
readonly schemas: Readonly<Partial<Record<ArtifactCapabilityName, ArtifactSchema>>>;
|
|
41
|
+
readonly idempotency: Readonly<Partial<Record<ArtifactCapabilityName, {
|
|
42
|
+
readonly required: true;
|
|
43
|
+
readonly scope: 'principal';
|
|
44
|
+
}>>>;
|
|
45
|
+
validate(name: string, args: unknown, envelopeKey?: string): Readonly<Record<string, JsonValue>>;
|
|
46
|
+
assertSelected(name: string): asserts name is ArtifactCapabilityName;
|
|
47
|
+
capabilityForRoute(method: string, path: string): ArtifactCapabilityName | undefined;
|
|
48
|
+
}
|
|
49
|
+
export interface CompiledValidators {
|
|
50
|
+
readonly validateBindingName: (value: unknown) => boolean;
|
|
51
|
+
readonly validateCallerKey: (value: unknown) => boolean;
|
|
52
|
+
readonly validateFileEntry: (entry: unknown) => boolean;
|
|
53
|
+
readonly normalizeCommand: (command: unknown) => EffectiveArtifactCommand;
|
|
54
|
+
}
|
|
55
|
+
/** Projection fields are data-only; invocation correlation is added by L6. */
|
|
56
|
+
export declare class ArtifactProfileInputError extends Error {
|
|
57
|
+
readonly kind: 'operational' | 'ordinary';
|
|
58
|
+
readonly status: number;
|
|
59
|
+
readonly httpStatus: number;
|
|
60
|
+
readonly variant: 'unselected_operation' | 'invalid_request';
|
|
61
|
+
readonly publicCode: string;
|
|
62
|
+
readonly category: 'invalid_request' | 'capability_unselected';
|
|
63
|
+
readonly retriable = false;
|
|
64
|
+
readonly phase: 'selection' | 'entry';
|
|
65
|
+
readonly commitState = "not_committed";
|
|
66
|
+
constructor(unselected?: boolean);
|
|
67
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const PROFILE_CONTRACT_VERSION = 'artifacts-profile/v1';
|
|
2
|
+
export const ARTIFACT_CAPABILITY_NAMES = [
|
|
3
|
+
'artifacts_get_template', 'artifacts_get_api_guide', 'artifacts_ensure',
|
|
4
|
+
'artifacts_publish', 'artifacts_create_upload', 'artifacts_commit_upload',
|
|
5
|
+
'artifacts_list', 'artifacts_get', 'artifacts_get_source', 'artifacts_fork',
|
|
6
|
+
'artifacts_set_access', 'artifacts_promote', 'artifacts_renew',
|
|
7
|
+
'artifacts_delete', 'artifacts_restore',
|
|
8
|
+
];
|
|
9
|
+
/** Projection fields are data-only; invocation correlation is added by L6. */
|
|
10
|
+
export class ArtifactProfileInputError extends Error {
|
|
11
|
+
kind;
|
|
12
|
+
status;
|
|
13
|
+
httpStatus;
|
|
14
|
+
variant;
|
|
15
|
+
publicCode;
|
|
16
|
+
category;
|
|
17
|
+
retriable = false;
|
|
18
|
+
phase;
|
|
19
|
+
commitState = 'not_committed';
|
|
20
|
+
constructor(unselected = false) {
|
|
21
|
+
super(unselected ? 'capability_unavailable' : 'invalid_request');
|
|
22
|
+
this.name = 'ArtifactProfileInputError';
|
|
23
|
+
this.kind = unselected ? 'operational' : 'ordinary';
|
|
24
|
+
this.status = unselected ? 503 : 400;
|
|
25
|
+
this.httpStatus = this.status;
|
|
26
|
+
this.variant = unselected ? 'unselected_operation' : 'invalid_request';
|
|
27
|
+
this.publicCode = this.message;
|
|
28
|
+
this.category = unselected ? 'capability_unselected' : 'invalid_request';
|
|
29
|
+
this.phase = unselected ? 'selection' : 'entry';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ArtifactProviderProfile, type CompiledArtifactsProfile } from './contracts.js';
|
|
2
|
+
export * from './contracts.js';
|
|
3
|
+
export { RADAR_ARTIFACTS_PROFILE } from './radar.js';
|
|
4
|
+
export declare function assertCompiledArtifactsProfile(value: unknown): asserts value is CompiledArtifactsProfile;
|
|
5
|
+
/** Compile once, before any registry, adapter, schema or integrity evidence. */
|
|
6
|
+
export declare function compileArtifactsProfile(input: ArtifactProviderProfile): CompiledArtifactsProfile;
|