@absolutejs/artifacts 0.0.4 → 0.1.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 CHANGED
@@ -87,6 +87,27 @@ const history = await artifacts.listRevisions("owner-123", page.id);
87
87
  const restored = await artifacts.restore("owner-123", page.id, 1);
88
88
  ```
89
89
 
90
+ ## Production persistence
91
+
92
+ Use the package-owned Drizzle schema on PostgreSQL, including Neon. The store
93
+ atomically writes the current artifact, immutable revision, and lifecycle
94
+ outbox events. It also persists per-revision indexing state and fences every
95
+ artifact read and mutation by owner.
96
+
97
+ ```ts
98
+ import {
99
+ artifactDrizzleSchema,
100
+ createDrizzleArtifactStore,
101
+ } from "@absolutejs/artifacts/drizzle";
102
+
103
+ const store = createDrizzleArtifactStore({ db });
104
+ ```
105
+
106
+ Export `artifactDrizzleSchema` from your application's Drizzle schema so its
107
+ normal migration workflow owns the four tables. Insert and select TypeBoxes
108
+ generated directly from those tables are exported from the same entry point;
109
+ hosts should reuse them instead of redefining database row schemas.
110
+
90
111
  ## File-backed artifact kinds
91
112
 
92
113
  Use the bundled definitions directly or compose them with application-specific
@@ -0,0 +1,245 @@
1
+ // @bun
2
+ // src/drizzle.ts
3
+ import { and, asc, desc, eq, isNotNull, isNull } from "drizzle-orm";
4
+ import {
5
+ customType,
6
+ index,
7
+ integer,
8
+ pgTable,
9
+ primaryKey,
10
+ text,
11
+ timestamp
12
+ } from "drizzle-orm/pg-core";
13
+ import { createInsertSchema, createSelectSchema } from "drizzle-typebox";
14
+ var recordJsonb = customType({
15
+ dataType: () => "jsonb",
16
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
17
+ toDriver: (value) => JSON.stringify(value)
18
+ });
19
+ var revisionJsonb = customType({
20
+ dataType: () => "jsonb",
21
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
22
+ toDriver: (value) => JSON.stringify(value)
23
+ });
24
+ var eventJsonb = customType({
25
+ dataType: () => "jsonb",
26
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
27
+ toDriver: (value) => JSON.stringify(value)
28
+ });
29
+ var indexingJsonb = customType({
30
+ dataType: () => "jsonb",
31
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
32
+ toDriver: (value) => JSON.stringify(value)
33
+ });
34
+ var artifactRecords = pgTable("artifact_records", {
35
+ document: recordJsonb().notNull(),
36
+ id: text().primaryKey(),
37
+ kind: text().notNull(),
38
+ ownerId: text("owner_id").notNull(),
39
+ revision: integer().notNull(),
40
+ status: text().notNull(),
41
+ updatedAt: timestamp("updated_at", {
42
+ mode: "string",
43
+ withTimezone: true
44
+ }).notNull()
45
+ }, (table) => [
46
+ index("artifact_records_owner_updated_idx").on(table.ownerId, table.updatedAt.desc()),
47
+ index("artifact_records_owner_kind_idx").on(table.ownerId, table.kind)
48
+ ]);
49
+ var artifactRevisions = pgTable("artifact_revisions", {
50
+ artifactId: text("artifact_id").notNull().references(() => artifactRecords.id),
51
+ document: revisionJsonb().notNull(),
52
+ ownerId: text("owner_id").notNull(),
53
+ revision: integer().notNull()
54
+ }, (table) => [
55
+ primaryKey({
56
+ columns: [table.artifactId, table.revision],
57
+ name: "artifact_revisions_pkey"
58
+ }),
59
+ index("artifact_revisions_owner_idx").on(table.ownerId, table.artifactId, table.revision.desc())
60
+ ]);
61
+ var artifactEvents = pgTable("artifact_events", {
62
+ artifactId: text("artifact_id").notNull().references(() => artifactRecords.id),
63
+ createdAt: timestamp("created_at", {
64
+ mode: "string",
65
+ withTimezone: true
66
+ }).notNull(),
67
+ document: eventJsonb().notNull(),
68
+ id: text().primaryKey(),
69
+ ownerId: text("owner_id").notNull(),
70
+ processedAt: timestamp("processed_at", {
71
+ mode: "string",
72
+ withTimezone: true
73
+ }),
74
+ type: text().notNull()
75
+ }, (table) => [
76
+ index("artifact_events_outbox_idx").on(table.processedAt, table.createdAt),
77
+ index("artifact_events_artifact_idx").on(table.ownerId, table.artifactId, table.createdAt)
78
+ ]);
79
+ var artifactIndexingStates = pgTable("artifact_indexing_states", {
80
+ artifactId: text("artifact_id").primaryKey().references(() => artifactRecords.id),
81
+ document: indexingJsonb().notNull(),
82
+ ownerId: text("owner_id").notNull(),
83
+ revision: integer().notNull(),
84
+ status: text().notNull(),
85
+ updatedAt: timestamp("updated_at", {
86
+ mode: "string",
87
+ withTimezone: true
88
+ }).notNull()
89
+ });
90
+ var artifactDrizzleSchema = {
91
+ artifactEvents,
92
+ artifactIndexingStates,
93
+ artifactRecords,
94
+ artifactRevisions
95
+ };
96
+ var ArtifactRecordInsertSchema = createInsertSchema(artifactRecords);
97
+ var ArtifactRecordSelectSchema = createSelectSchema(artifactRecords);
98
+ var ArtifactRevisionInsertSchema = createInsertSchema(artifactRevisions);
99
+ var ArtifactRevisionSelectSchema = createSelectSchema(artifactRevisions);
100
+ var ArtifactEventInsertSchema = createInsertSchema(artifactEvents);
101
+ var ArtifactEventSelectSchema = createSelectSchema(artifactEvents);
102
+ var ArtifactIndexingStateInsertSchema = createInsertSchema(artifactIndexingStates);
103
+ var ArtifactIndexingStateSelectSchema = createSelectSchema(artifactIndexingStates);
104
+ var eventRows = (events) => events.map((event) => ({
105
+ artifactId: event.artifactId,
106
+ createdAt: event.createdAt,
107
+ document: event,
108
+ id: event.id,
109
+ ownerId: event.ownerId,
110
+ processedAt: event.processedAt,
111
+ type: event.type
112
+ }));
113
+ var assertEventsBelongToArtifact = (record, events) => {
114
+ if (events.some((event) => event.artifactId !== record.id || event.ownerId !== record.ownerId))
115
+ throw new Error("Artifact events must belong to the persisted artifact");
116
+ };
117
+ var recordRow = (record) => ({
118
+ document: record,
119
+ id: record.id,
120
+ kind: record.kind,
121
+ ownerId: record.ownerId,
122
+ revision: record.revision,
123
+ status: record.status,
124
+ updatedAt: record.updatedAt
125
+ });
126
+ var recordUpdate = (record) => ({
127
+ document: record,
128
+ kind: record.kind,
129
+ ownerId: record.ownerId,
130
+ revision: record.revision,
131
+ status: record.status,
132
+ updatedAt: record.updatedAt
133
+ });
134
+ var revisionRow = (record) => ({
135
+ artifactId: record.id,
136
+ document: record,
137
+ ownerId: record.ownerId,
138
+ revision: record.revision
139
+ });
140
+ var createDrizzleArtifactStore = (options) => ({
141
+ create: (record, events = []) => options.db.transaction(async (transaction) => {
142
+ assertEventsBelongToArtifact(record, events);
143
+ await transaction.insert(artifactRecords).values(recordRow(record));
144
+ await transaction.insert(artifactRevisions).values(revisionRow(record));
145
+ if (events.length > 0)
146
+ await transaction.insert(artifactEvents).values(eventRows(events));
147
+ }),
148
+ get: async (ownerId, artifactId) => {
149
+ const [row] = await options.db.select({ document: artifactRecords.document }).from(artifactRecords).where(and(eq(artifactRecords.id, artifactId), eq(artifactRecords.ownerId, ownerId))).limit(1);
150
+ return row?.document ?? null;
151
+ },
152
+ getIndexingState: async (ownerId, artifactId) => {
153
+ const [row] = await options.db.select({ document: artifactIndexingStates.document }).from(artifactIndexingStates).where(and(eq(artifactIndexingStates.artifactId, artifactId), eq(artifactIndexingStates.ownerId, ownerId))).limit(1);
154
+ return row?.document ?? null;
155
+ },
156
+ getRevision: async (ownerId, artifactId, revision) => {
157
+ const [row] = await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions).where(and(eq(artifactRevisions.artifactId, artifactId), eq(artifactRevisions.ownerId, ownerId), eq(artifactRevisions.revision, revision))).limit(1);
158
+ return row?.document ?? null;
159
+ },
160
+ list: async (ownerId, query = {}) => {
161
+ const conditions = [eq(artifactRecords.ownerId, ownerId)];
162
+ if (query.kind)
163
+ conditions.push(eq(artifactRecords.kind, query.kind));
164
+ if (query.status)
165
+ conditions.push(eq(artifactRecords.status, query.status));
166
+ const statement = options.db.select({ document: artifactRecords.document }).from(artifactRecords).where(and(...conditions)).orderBy(desc(artifactRecords.updatedAt));
167
+ const rows = query.limit === undefined ? await statement : await statement.limit(query.limit);
168
+ return rows.map(({ document }) => document);
169
+ },
170
+ listEvents: async (query = {}) => {
171
+ const conditions = [];
172
+ if (query.processed !== undefined)
173
+ conditions.push(query.processed ? isNotNull(artifactEvents.processedAt) : isNull(artifactEvents.processedAt));
174
+ if (query.type)
175
+ conditions.push(eq(artifactEvents.type, query.type));
176
+ const statement = options.db.select({
177
+ document: artifactEvents.document,
178
+ processedAt: artifactEvents.processedAt
179
+ }).from(artifactEvents).where(conditions.length > 0 ? and(...conditions) : undefined).orderBy(asc(artifactEvents.createdAt));
180
+ const rows = query.limit === undefined ? await statement : await statement.limit(query.limit);
181
+ return rows.map(({ document, processedAt }) => ({
182
+ ...document,
183
+ ...processedAt ? { processedAt: new Date(processedAt).toISOString() } : {}
184
+ }));
185
+ },
186
+ listReferencedAssetIds: async () => {
187
+ const rows = await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions);
188
+ return [
189
+ ...new Set(rows.flatMap(({ document }) => document.assets.map(({ id }) => id)))
190
+ ];
191
+ },
192
+ listRevisions: async (ownerId, artifactId) => (await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions).where(and(eq(artifactRevisions.artifactId, artifactId), eq(artifactRevisions.ownerId, ownerId))).orderBy(desc(artifactRevisions.revision))).map(({ document }) => document),
193
+ markEventProcessed: async (eventId, processedAt) => (await options.db.update(artifactEvents).set({ processedAt }).where(eq(artifactEvents.id, eventId)).returning({ id: artifactEvents.id })).length === 1,
194
+ putIndexingState: (ownerId, state, events = []) => options.db.transaction(async (transaction) => {
195
+ assertEventsBelongToArtifact({ id: state.artifactId, ownerId }, events);
196
+ const [artifact] = await transaction.select({ id: artifactRecords.id }).from(artifactRecords).where(and(eq(artifactRecords.id, state.artifactId), eq(artifactRecords.ownerId, ownerId))).limit(1);
197
+ if (!artifact)
198
+ throw new Error("Artifact not found");
199
+ await transaction.insert(artifactIndexingStates).values({
200
+ artifactId: state.artifactId,
201
+ document: state,
202
+ ownerId,
203
+ revision: state.revision,
204
+ status: state.status,
205
+ updatedAt: state.updatedAt
206
+ }).onConflictDoUpdate({
207
+ set: {
208
+ document: state,
209
+ ownerId,
210
+ revision: state.revision,
211
+ status: state.status,
212
+ updatedAt: state.updatedAt
213
+ },
214
+ target: artifactIndexingStates.artifactId
215
+ });
216
+ if (events.length > 0)
217
+ await transaction.insert(artifactEvents).values(eventRows(events));
218
+ }),
219
+ save: (record, expectedRevision, events = []) => options.db.transaction(async (transaction) => {
220
+ assertEventsBelongToArtifact(record, events);
221
+ const updated = await transaction.update(artifactRecords).set(recordUpdate(record)).where(and(eq(artifactRecords.id, record.id), eq(artifactRecords.ownerId, record.ownerId), eq(artifactRecords.revision, expectedRevision))).returning({ id: artifactRecords.id });
222
+ if (updated.length !== 1)
223
+ return false;
224
+ await transaction.insert(artifactRevisions).values(revisionRow(record));
225
+ if (events.length > 0)
226
+ await transaction.insert(artifactEvents).values(eventRows(events));
227
+ return true;
228
+ })
229
+ });
230
+ export {
231
+ createDrizzleArtifactStore,
232
+ artifactRevisions,
233
+ artifactRecords,
234
+ artifactIndexingStates,
235
+ artifactEvents,
236
+ artifactDrizzleSchema,
237
+ ArtifactRevisionSelectSchema,
238
+ ArtifactRevisionInsertSchema,
239
+ ArtifactRecordSelectSchema,
240
+ ArtifactRecordInsertSchema,
241
+ ArtifactIndexingStateSelectSchema,
242
+ ArtifactIndexingStateInsertSchema,
243
+ ArtifactEventSelectSchema,
244
+ ArtifactEventInsertSchema
245
+ };
package/dist/manifest.js CHANGED
@@ -14,14 +14,23 @@ var __export = (target, all) => {
14
14
  set: __exportSetter.bind(all, name)
15
15
  });
16
16
  };
17
- var defineManifest = () => (manifest) => {
18
- const defined = manifest;
17
+ var defineImplementation = () => (implementation) => {
18
+ const defined = implementation;
19
19
  return defined;
20
20
  };
21
- var toolFactory = () => ({
22
- runtime: (definition) => ({ kind: "runtime", ...definition }),
23
- workspace: (definition) => ({ kind: "workspace", ...definition })
24
- });
21
+ var defineManifest = () => (manifest) => manifest;
22
+ var literal = (value) => value;
23
+ var RUNTIME_KIND = literal("runtime");
24
+ var WORKSPACE_KIND = literal("workspace");
25
+ var toolFactory = () => {
26
+ function runtime(definition) {
27
+ return { kind: RUNTIME_KIND, ...definition };
28
+ }
29
+ function workspace(definition) {
30
+ return { kind: WORKSPACE_KIND, ...definition };
31
+ }
32
+ return { runtime, workspace };
33
+ };
25
34
  function IsAsyncIterator(value) {
26
35
  return IsObject(value) && globalThis.Symbol.asyncIterator in value;
27
36
  }
@@ -759,7 +768,7 @@ function String2(options) {
759
768
  function* FromUnion(syntax) {
760
769
  const trim = syntax.trim().replace(/"|'/g, "");
761
770
  return trim === "boolean" ? yield Boolean() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt2() : trim === "string" ? yield String2() : yield (() => {
762
- const literals = trim.split("|").map((literal) => Literal(literal.trim()));
771
+ const literals = trim.split("|").map((literal2) => Literal(literal2.trim()));
763
772
  return literals.length === 0 ? Never() : literals.length === 1 ? literals[0] : UnionEvaluated(literals);
764
773
  })();
765
774
  }
@@ -3467,10 +3476,10 @@ function ScoreUnion(schema, references, value) {
3467
3476
  const keys = Object.getOwnPropertyNames(value);
3468
3477
  const entries = Object.entries(object.properties);
3469
3478
  return entries.reduce((acc, [key, schema2]) => {
3470
- const literal = schema2[Kind] === "Literal" && schema2.const === value[key] ? 100 : 0;
3479
+ const literal2 = schema2[Kind] === "Literal" && schema2.const === value[key] ? 100 : 0;
3471
3480
  const checks = Check(schema2, references, value[key]) ? 10 : 0;
3472
3481
  const exists = keys.includes(key) ? 1 : 0;
3473
- return acc + (literal + checks + exists);
3482
+ return acc + (literal2 + checks + exists);
3474
3483
  }, 0);
3475
3484
  } else if (schema[Kind] === "Union") {
3476
3485
  const schemas = schema.anyOf.map((schema2) => Deref(schema2, references));
@@ -5807,7 +5816,13 @@ var wiringSnippet = Type.Object({
5807
5816
  Type.Literal("server-plugin")
5808
5817
  ]))
5809
5818
  });
5810
- var clientFrameworks = ["angular", "client", "react", "svelte", "vue"];
5819
+ var clientFrameworks = [
5820
+ "angular",
5821
+ "client",
5822
+ "react",
5823
+ "svelte",
5824
+ "vue"
5825
+ ];
5811
5826
  var wiringRecipe = Type.Object({
5812
5827
  client: Type.Optional(Type.Partial(Type.Object(Object.fromEntries(clientFrameworks.map((framework) => [framework, wiringSnippet]))))),
5813
5828
  description: Type.Optional(Type.String()),
@@ -5872,8 +5887,47 @@ var toolAnnotations = Type.Object({
5872
5887
  readOnlyHint: Type.Optional(Type.Boolean()),
5873
5888
  title: Type.Optional(Type.String())
5874
5889
  });
5890
+ var toolAuthorization = Type.Object({
5891
+ approval: Type.Union([
5892
+ Type.Literal("always"),
5893
+ Type.Literal("never"),
5894
+ Type.Literal("policy")
5895
+ ]),
5896
+ audience: Type.Union([
5897
+ Type.Literal("admin"),
5898
+ Type.Literal("authenticated"),
5899
+ Type.Literal("owner"),
5900
+ Type.Literal("public")
5901
+ ]),
5902
+ compensatingTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })),
5903
+ destinationFields: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
5904
+ destinations: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
5905
+ effects: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
5906
+ idempotency: Type.Optional(Type.Union([
5907
+ Type.Object({
5908
+ field: Type.String({ minLength: 1 }),
5909
+ mode: Type.Literal("field")
5910
+ }),
5911
+ Type.Object({ mode: Type.Literal("host") }),
5912
+ Type.Object({ mode: Type.Literal("resource") })
5913
+ ])),
5914
+ requiredScopes: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
5915
+ resource: Type.Optional(Type.Object({
5916
+ idField: Type.Optional(Type.String({ minLength: 1 })),
5917
+ ownerIdField: Type.Optional(Type.String({ minLength: 1 })),
5918
+ tenantIdField: Type.Optional(Type.String({ minLength: 1 })),
5919
+ type: Type.String({ minLength: 1 })
5920
+ })),
5921
+ reversible: Type.Optional(Type.Boolean()),
5922
+ spend: Type.Optional(Type.Object({
5923
+ amountMinorField: Type.String({ minLength: 1 }),
5924
+ currencyField: Type.String({ minLength: 1 }),
5925
+ maximumAmountMinor: Type.Optional(Type.Integer({ minimum: 0 }))
5926
+ }))
5927
+ });
5875
5928
  var serializedTool = Type.Object({
5876
5929
  annotations: Type.Optional(toolAnnotations),
5930
+ authorization: Type.Optional(toolAuthorization),
5877
5931
  capabilities: Type.Optional(Type.Array(Type.Union([
5878
5932
  Type.Literal("exec"),
5879
5933
  Type.Literal("glob"),
@@ -5885,7 +5939,15 @@ var serializedTool = Type.Object({
5885
5939
  kind: Type.Union([Type.Literal("runtime"), Type.Literal("workspace")])
5886
5940
  });
5887
5941
  var manifestSchema = Type.Object({
5888
- contract: Type.Literal(1),
5942
+ contract: Type.Union([Type.Literal(1), Type.Literal(2)]),
5943
+ discovery: Type.Optional(Type.Object({
5944
+ audiences: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
5945
+ certificationUrl: Type.Optional(Type.String()),
5946
+ intents: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
5947
+ keywords: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
5948
+ protocols: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
5949
+ url: Type.Optional(Type.String())
5950
+ })),
5889
5951
  identity: Type.Object({
5890
5952
  accent: Type.Optional(Type.String({ pattern: "^#[0-9a-fA-F]{3,8}$" })),
5891
5953
  category: Type.String({ minLength: 1 }),
@@ -5895,7 +5957,9 @@ var manifestSchema = Type.Object({
5895
5957
  svg: Type.Optional(Type.String()),
5896
5958
  url: Type.Optional(Type.String())
5897
5959
  })),
5898
- name: Type.String({ pattern: "^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$" }),
5960
+ name: Type.String({
5961
+ pattern: "^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$"
5962
+ }),
5899
5963
  tagline: Type.String({ minLength: 1 })
5900
5964
  }),
5901
5965
  implements: Type.Optional(Type.Array(adapterImplementation)),
@@ -5917,7 +5981,7 @@ var manifestSchema = Type.Object({
5917
5981
  import { Type as Type2 } from "@sinclair/typebox";
5918
5982
  var tool = toolFactory();
5919
5983
  var manifest = defineManifest()({
5920
- contract: 1,
5984
+ contract: 2,
5921
5985
  identity: {
5922
5986
  accent: "#8b5cf6",
5923
5987
  category: "ai",
@@ -5926,19 +5990,80 @@ var manifest = defineManifest()({
5926
5990
  name: "@absolutejs/artifacts",
5927
5991
  tagline: "Give everything your AI makes a real lifecycle."
5928
5992
  },
5993
+ implements: [
5994
+ defineImplementation()({
5995
+ contract: "artifacts/store",
5996
+ factory: "createMemoryArtifactStore",
5997
+ from: "@absolutejs/artifacts",
5998
+ title: "In memory (development only \u2014 history resets on restart)",
5999
+ wiring: {
6000
+ code: "createMemoryArtifactStore()",
6001
+ imports: [
6002
+ {
6003
+ from: "@absolutejs/artifacts",
6004
+ names: ["createMemoryArtifactStore"]
6005
+ }
6006
+ ]
6007
+ }
6008
+ }),
6009
+ defineImplementation()({
6010
+ contract: "artifacts/store",
6011
+ factory: "createDrizzleArtifactStore",
6012
+ from: "@absolutejs/artifacts/drizzle",
6013
+ requires: {
6014
+ peers: [
6015
+ {
6016
+ name: "drizzle-orm",
6017
+ range: ">=1.0.0-rc.4 <2",
6018
+ reason: "Typed artifact revisions, indexing state, and transactional outbox persistence"
6019
+ }
6020
+ ],
6021
+ services: [
6022
+ {
6023
+ description: "Artifact lifecycle and revision database",
6024
+ id: "postgres"
6025
+ }
6026
+ ]
6027
+ },
6028
+ title: "Drizzle Postgres (production, including Neon)",
6029
+ wiring: {
6030
+ code: "createDrizzleArtifactStore({ db })",
6031
+ imports: [
6032
+ {
6033
+ from: "@absolutejs/artifacts/drizzle",
6034
+ names: ["createDrizzleArtifactStore"]
6035
+ }
6036
+ ]
6037
+ }
6038
+ })
6039
+ ],
5929
6040
  settings: Type2.Object({}),
5930
6041
  slots: {
5931
- service: {
6042
+ store: {
5932
6043
  configPath: "$self",
5933
- contract: "artifacts/service",
5934
- description: "The host-configured artifact service",
5935
- known: [],
6044
+ contract: "artifacts/store",
6045
+ description: "Where current artifacts, immutable revisions, indexing state, and transactional outbox events live",
6046
+ known: [
6047
+ "@absolutejs/artifacts#createMemoryArtifactStore",
6048
+ "@absolutejs/artifacts#drizzle"
6049
+ ],
5936
6050
  required: true
5937
6051
  }
5938
6052
  },
5939
6053
  tools: {
5940
6054
  artifact_get: tool.runtime({
5941
6055
  annotations: { readOnlyHint: true },
6056
+ authorization: {
6057
+ approval: "never",
6058
+ audience: "owner",
6059
+ effects: ["read"],
6060
+ requiredScopes: ["artifacts:read"],
6061
+ resource: {
6062
+ idField: "artifactId",
6063
+ ownerIdField: "ownerId",
6064
+ type: "artifact"
6065
+ }
6066
+ },
5942
6067
  description: "Open one artifact owned by a user.",
5943
6068
  handler: async ({ artifactId, ownerId }, service) => JSON.stringify(await service.get(ownerId, artifactId)),
5944
6069
  input: Type2.Object({
@@ -5948,6 +6073,13 @@ var manifest = defineManifest()({
5948
6073
  }),
5949
6074
  artifact_list: tool.runtime({
5950
6075
  annotations: { readOnlyHint: true },
6076
+ authorization: {
6077
+ approval: "never",
6078
+ audience: "owner",
6079
+ effects: ["read"],
6080
+ requiredScopes: ["artifacts:read"],
6081
+ resource: { ownerIdField: "ownerId", type: "artifact" }
6082
+ },
5951
6083
  description: "List artifacts owned by a user.",
5952
6084
  handler: async ({ kind, ownerId }, service) => JSON.stringify(await service.list(ownerId, { kind })),
5953
6085
  input: Type2.Object({
@@ -5957,6 +6089,17 @@ var manifest = defineManifest()({
5957
6089
  }),
5958
6090
  artifact_history: tool.runtime({
5959
6091
  annotations: { readOnlyHint: true },
6092
+ authorization: {
6093
+ approval: "never",
6094
+ audience: "owner",
6095
+ effects: ["read"],
6096
+ requiredScopes: ["artifacts:read"],
6097
+ resource: {
6098
+ idField: "artifactId",
6099
+ ownerIdField: "ownerId",
6100
+ type: "artifact-revision"
6101
+ }
6102
+ },
5960
6103
  description: "List immutable revisions of one artifact owned by a user.",
5961
6104
  handler: async ({ artifactId, ownerId }, service) => JSON.stringify(await service.listRevisions(ownerId, artifactId)),
5962
6105
  input: Type2.Object({
@@ -5965,6 +6108,19 @@ var manifest = defineManifest()({
5965
6108
  })
5966
6109
  }),
5967
6110
  artifact_restore: tool.runtime({
6111
+ authorization: {
6112
+ approval: "policy",
6113
+ audience: "owner",
6114
+ effects: ["write"],
6115
+ idempotency: { mode: "host" },
6116
+ requiredScopes: ["artifacts:write"],
6117
+ resource: {
6118
+ idField: "artifactId",
6119
+ ownerIdField: "ownerId",
6120
+ type: "artifact-revision"
6121
+ },
6122
+ reversible: false
6123
+ },
5968
6124
  description: "Restore an old artifact revision as a new private draft.",
5969
6125
  handler: async ({ artifactId, ownerId, revision }, service) => JSON.stringify(await service.restore(ownerId, artifactId, revision)),
5970
6126
  input: Type2.Object({
@@ -5988,7 +6144,7 @@ var manifest = defineManifest()({
5988
6144
  "\t}",
5989
6145
  "});",
5990
6146
  "",
5991
- "const artifactStore = createMemoryArtifactStore();",
6147
+ "const artifactStore = ${slot.store};",
5992
6148
  "const artifactService = createArtifactService({",
5993
6149
  "\tregistry: artifactRegistry,",
5994
6150
  "\tstore: artifactStore",
@@ -5998,11 +6154,7 @@ var manifest = defineManifest()({
5998
6154
  imports: [
5999
6155
  {
6000
6156
  from: "@absolutejs/artifacts",
6001
- names: [
6002
- "createArtifactService",
6003
- "createMemoryArtifactStore",
6004
- "defineArtifactRegistry"
6005
- ]
6157
+ names: ["createArtifactService", "defineArtifactRegistry"]
6006
6158
  },
6007
6159
  { from: "@sinclair/typebox", names: ["Type"] }
6008
6160
  ],