@hasna/instructions 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +18 -4
  2. package/dist/chunks/{apply-7svah2qm.js → apply-c3sd4agz.js} +2 -2
  3. package/dist/chunks/{apply-jp13sa1e.js → apply-pnn7a3y7.js} +2 -2
  4. package/dist/chunks/{index-7m4j8a33.js → index-6jncnnw7.js} +117 -4
  5. package/dist/chunks/{index-4pfq42t5.js → index-aj66f6xr.js} +118 -27
  6. package/dist/chunks/{index-bzyxvwcd.js → index-jg8ptcwh.js} +2 -2
  7. package/dist/chunks/{index-arrrx0ed.js → index-mvckkf15.js} +39 -20
  8. package/dist/chunks/{index-1cnyjnd7.js → index-pdpg8a44.js} +2 -2
  9. package/dist/chunks/{index-z3ma4aqk.js → index-r7nfef2g.js} +1 -1
  10. package/dist/chunks/{index-fwbs6tma.js → index-ypcef3a2.js} +1 -1
  11. package/dist/chunks/{local-5wvv5xv3.js → local-0a9gja58.js} +141 -1
  12. package/dist/chunks/{local-zxa5dpf4.js → local-969ye538.js} +141 -1
  13. package/dist/chunks/{s3-backup-n2z4fwyh.js → s3-backup-hxe3zpfz.js} +1 -1
  14. package/dist/chunks/{s3-object-store-90tgbh6k.js → s3-object-store-n0s82swt.js} +1 -1
  15. package/dist/chunks/{sync-r8t7zsp3.js → sync-q5hvwq6e.js} +3 -3
  16. package/dist/chunks/{sync-2075deve.js → sync-xtkbm5br.js} +3 -3
  17. package/dist/cli/index.js +269 -53
  18. package/dist/data/config-store.d.ts +10 -2
  19. package/dist/data/config-store.d.ts.map +1 -1
  20. package/dist/db/configs.d.ts +4 -1
  21. package/dist/db/configs.d.ts.map +1 -1
  22. package/dist/db/local.d.ts +1 -1
  23. package/dist/db/local.d.ts.map +1 -1
  24. package/dist/index.js +282 -36
  25. package/dist/lib/compact-output.d.ts +2 -18
  26. package/dist/lib/compact-output.d.ts.map +1 -1
  27. package/dist/lib/export.d.ts.map +1 -1
  28. package/dist/lib/import.d.ts.map +1 -1
  29. package/dist/mcp/index.js +17 -17
  30. package/dist/mcp/server.d.ts.map +1 -1
  31. package/dist/sdk/index.js +27 -3
  32. package/dist/sdk/v1-client.d.ts +4 -3
  33. package/dist/sdk/v1-client.d.ts.map +1 -1
  34. package/dist/sdk/v1.generated.d.ts +32 -2
  35. package/dist/sdk/v1.generated.d.ts.map +1 -1
  36. package/dist/server/index.d.ts +1 -1
  37. package/dist/server/index.d.ts.map +1 -1
  38. package/dist/server/index.js +93 -7
  39. package/dist/server/openapi.d.ts +117 -3
  40. package/dist/server/openapi.d.ts.map +1 -1
  41. package/dist/server/v1.d.ts.map +1 -1
  42. package/dist/storage/cloud-store.d.ts +2 -15
  43. package/dist/storage/cloud-store.d.ts.map +1 -1
  44. package/dist/storage/index.js +39 -20
  45. package/dist/storage/s3-object-store.d.ts.map +1 -1
  46. package/dist/types/index.d.ts +33 -0
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/package.json +3 -3
package/README.md CHANGED
@@ -52,9 +52,13 @@ existing row.
52
52
 
53
53
  ```bash
54
54
  instructions --help
55
- instructions list # compact, paged summary
56
- instructions list --verbose # expanded metadata, still paged
57
- instructions list --json # full machine-readable records
55
+ instructions list # compact, paged summary
56
+ instructions list --verbose # expanded metadata, still paged
57
+ instructions list --json # legacy complete full-record array
58
+ instructions list --json --detail compact --limit 20 # bounded identity envelope
59
+ instructions list --json --detail compact --fields id,slug,name,version
60
+ instructions list --json --detail full --limit 20 # explicit bounded content read
61
+ instructions list --json --detail compact --all # explicit complete metadata read
58
62
  instructions show <slug> # full metadata + content
59
63
  instructions inspect <slug> # alias for show
60
64
  instructions profile resolve
@@ -68,7 +72,9 @@ small. Human output is capped at 20 rows unless you pass `--limit`; use
68
72
  `--cursor` to continue from the next page. Detail is explicit:
69
73
 
70
74
  - `--verbose` expands list rows with descriptions, tags, and paths.
71
- - `--json` preserves full machine-readable records for automation.
75
+ - Legacy `--json` with no modern detail flags preserves the complete full-record array for automation. Explicit `--limit`/`--cursor` now bound that legacy array.
76
+ - `--detail compact` returns a content-free `{ configs, _meta }` identity envelope through the already-deployed `/v1/configs?view=identity` projection. Add `--fields` (including immutable `id`), `--all`, or `--pretty` as needed.
77
+ - `--detail full` is the explicit content-bearing envelope; it is bounded unless `--all` is supplied.
72
78
  - `show`/`inspect` and `snapshot show` print full config or snapshot content.
73
79
 
74
80
  `instructions report --json` emits the stable `schema_version: 1` report
@@ -330,6 +336,14 @@ credentials may come from Bun's standard AWS chain (including an ECS task role);
330
336
  explicit static credentials are optional and must be a complete pair. Status
331
337
  never prints credential values or the bucket name.
332
338
 
339
+ The production deployment runs the immutable predeploy backup push and verify
340
+ as direct Bun commands in the exact candidate image. The GitHub runner alone
341
+ parses the push receipt, then supplies the recorded payload and manifest version
342
+ IDs to verification; it also checks the receipt digest and size, COMPLIANCE
343
+ Object Lock retention for both versions, and an exact versioned-payload
344
+ readback. Every backup gate completes before any ECR push, database migration,
345
+ or ECS update.
346
+
333
347
  The public importable surface is available at `@hasna/instructions/storage`.
334
348
 
335
349
  ## Data Directory
@@ -8,8 +8,8 @@ import {
8
8
  getConfigHome,
9
9
  normalizeTargetPath,
10
10
  previewConfigs
11
- } from "./index-fwbs6tma.js";
12
- import"./index-4pfq42t5.js";
11
+ } from "./index-ypcef3a2.js";
12
+ import"./index-aj66f6xr.js";
13
13
  import"./index-35z65jsa.js";
14
14
  import"./index-3djthcm6.js";
15
15
  import"./index-nnwp92tk.js";
@@ -8,8 +8,8 @@ import {
8
8
  getConfigHome,
9
9
  normalizeTargetPath,
10
10
  previewConfigs
11
- } from "./index-z3ma4aqk.js";
12
- import"./index-7m4j8a33.js";
11
+ } from "./index-r7nfef2g.js";
12
+ import"./index-6jncnnw7.js";
13
13
  import"./index-n3fjspr0.js";
14
14
  import"./index-fpeyzn3n.js";
15
15
  import"./index-bsan4c16.js";
@@ -11722,6 +11722,19 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
11722
11722
  const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
11723
11723
  return { ...page, source_bounded: false };
11724
11724
  }
11725
+ function projectBoundedPage(page, project) {
11726
+ return {
11727
+ items: page.items.map(project),
11728
+ total: page.total,
11729
+ limit: page.limit,
11730
+ cursor: page.cursor,
11731
+ next_cursor: page.next_cursor,
11732
+ has_more: page.has_more,
11733
+ complete: page.complete,
11734
+ truncated: page.truncated,
11735
+ source_bounded: page.source_bounded
11736
+ };
11737
+ }
11725
11738
 
11726
11739
  class CollectionChangedWhilePagingError extends Error {
11727
11740
  constructor(label, detail) {
@@ -11806,7 +11819,7 @@ function formatCliError(err, env = process.env) {
11806
11819
  var localStoreModulePromise = null;
11807
11820
  function localStoreModule() {
11808
11821
  if (!localStoreModulePromise)
11809
- localStoreModulePromise = import("./local-zxa5dpf4.js");
11822
+ localStoreModulePromise = import("./local-969ye538.js");
11810
11823
  return localStoreModulePromise;
11811
11824
  }
11812
11825
 
@@ -11820,6 +11833,15 @@ class LocalConfigStore {
11820
11833
  async listConfigs(filter) {
11821
11834
  return (await localStoreModule()).listConfigs(filter, this.db);
11822
11835
  }
11836
+ async listConfigsPage(filter = {}, options = {}) {
11837
+ return (await localStoreModule()).listConfigsPage(filter, options, this.db);
11838
+ }
11839
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
11840
+ return (await localStoreModule()).listConfigIdentitiesPage(filter, options, this.db);
11841
+ }
11842
+ async listConfigSummariesPage(filter = {}, options = {}) {
11843
+ return (await localStoreModule()).listConfigSummariesPage(filter, options, this.db);
11844
+ }
11823
11845
  async getConfig(idOrSlug) {
11824
11846
  return (await localStoreModule()).getConfig(idOrSlug, this.db);
11825
11847
  }
@@ -11923,6 +11945,43 @@ class LocalConfigStore {
11923
11945
  (await localStoreModule()).resetLocalDatabase();
11924
11946
  }
11925
11947
  }
11948
+ function toConfigIdentity(value) {
11949
+ const record = value && typeof value === "object" ? value : {};
11950
+ return {
11951
+ id: String(record.id ?? ""),
11952
+ name: String(record.name ?? ""),
11953
+ slug: String(record.slug ?? ""),
11954
+ kind: String(record.kind ?? ""),
11955
+ category: String(record.category ?? ""),
11956
+ agent: String(record.agent ?? ""),
11957
+ format: String(record.format ?? ""),
11958
+ is_template: Boolean(record.is_template),
11959
+ version: Number(record.version ?? 0),
11960
+ created_at: String(record.created_at ?? ""),
11961
+ updated_at: String(record.updated_at ?? ""),
11962
+ synced_at: record.synced_at == null ? null : String(record.synced_at)
11963
+ };
11964
+ }
11965
+ function toConfigSummary(value) {
11966
+ const record = value && typeof value === "object" ? value : {};
11967
+ const outputs = Array.isArray(record.outputs) ? record.outputs : [];
11968
+ return {
11969
+ id: String(record.id ?? ""),
11970
+ slug: String(record.slug ?? ""),
11971
+ name: String(record.name ?? ""),
11972
+ category: String(record.category ?? ""),
11973
+ agent: String(record.agent ?? ""),
11974
+ kind: String(record.kind ?? ""),
11975
+ format: String(record.format ?? ""),
11976
+ target_path: record.target_path == null ? null : String(record.target_path),
11977
+ output_count: Number(record.output_count ?? outputs.length),
11978
+ version: Number(record.version ?? 0),
11979
+ is_template: Boolean(record.is_template),
11980
+ ...record.updated_at !== undefined ? { updated_at: String(record.updated_at) } : {},
11981
+ ...record.description !== undefined ? { description: record.description == null ? null : String(record.description) } : {},
11982
+ ...Array.isArray(record.tags) ? { tags: record.tags.map(String) } : {}
11983
+ };
11984
+ }
11926
11985
 
11927
11986
  class CloudConfigStore {
11928
11987
  mode = "api";
@@ -11944,7 +12003,7 @@ class CloudConfigStore {
11944
12003
  throw err;
11945
12004
  }
11946
12005
  }
11947
- async listConfigsPageRemote(filter, options) {
12006
+ async listConfigsPage(filter = {}, options = {}) {
11948
12007
  const normalized = normalizeBoundedReadOptions(options);
11949
12008
  const params = new URLSearchParams;
11950
12009
  if (filter.category)
@@ -11955,13 +12014,67 @@ class CloudConfigStore {
11955
12014
  params.set("kind", filter.kind);
11956
12015
  if (filter.search)
11957
12016
  params.set("search", filter.search);
12017
+ for (const tag of filter.tags ?? [])
12018
+ params.append("tag", tag);
11958
12019
  params.set("limit", String(normalized.limit));
11959
12020
  params.set("cursor", String(normalized.cursor));
11960
12021
  const { data } = await this.request("GET", `/configs?${params.toString()}`);
11961
12022
  return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
11962
12023
  }
12024
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
12025
+ const normalized = normalizeBoundedReadOptions(options);
12026
+ const params = new URLSearchParams;
12027
+ if (filter.category)
12028
+ params.set("category", filter.category);
12029
+ if (filter.agent)
12030
+ params.set("agent", filter.agent);
12031
+ if (filter.kind)
12032
+ params.set("kind", filter.kind);
12033
+ if (filter.search)
12034
+ params.set("search", filter.search);
12035
+ for (const tag of filter.tags ?? [])
12036
+ params.append("tag", tag);
12037
+ params.set("view", "identity");
12038
+ params.set("limit", String(normalized.limit));
12039
+ params.set("cursor", String(normalized.cursor));
12040
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
12041
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config identity list");
12042
+ if (page.items.some((item) => {
12043
+ const record = item && typeof item === "object" ? item : {};
12044
+ return ["content", "target_path", "outputs", "description", "tags"].some((field) => Object.prototype.hasOwnProperty.call(record, field));
12045
+ })) {
12046
+ throw new Error("Instructions /v1 config identity projection is unavailable; deploy the identity endpoint before using compact lists");
12047
+ }
12048
+ return projectBoundedPage(page, toConfigIdentity);
12049
+ }
12050
+ async listConfigSummariesPage(filter = {}, options = {}) {
12051
+ const normalized = normalizeBoundedReadOptions(options);
12052
+ const params = new URLSearchParams;
12053
+ if (filter.category)
12054
+ params.set("category", filter.category);
12055
+ if (filter.agent)
12056
+ params.set("agent", filter.agent);
12057
+ if (filter.kind)
12058
+ params.set("kind", filter.kind);
12059
+ if (filter.search)
12060
+ params.set("search", filter.search);
12061
+ for (const tag of filter.tags ?? [])
12062
+ params.append("tag", tag);
12063
+ params.set("view", "summary");
12064
+ params.set("limit", String(normalized.limit));
12065
+ params.set("cursor", String(normalized.cursor));
12066
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
12067
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config summary list");
12068
+ if (page.items.some((item) => {
12069
+ const record = item && typeof item === "object" ? item : {};
12070
+ return Object.prototype.hasOwnProperty.call(record, "content") || Object.prototype.hasOwnProperty.call(record, "outputs");
12071
+ })) {
12072
+ throw new Error("Instructions /v1 config summary projection is unavailable; deploy the summary endpoint before using summary lists");
12073
+ }
12074
+ return projectBoundedPage(page, toConfigSummary);
12075
+ }
11963
12076
  async listConfigs(filter = {}) {
11964
- const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPageRemote(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
12077
+ const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPage(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
11965
12078
  let filtered = configs;
11966
12079
  if (filter.tags && filter.tags.length > 0) {
11967
12080
  filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
@@ -12027,7 +12140,7 @@ class CloudConfigStore {
12027
12140
  return data?.pruned ?? 0;
12028
12141
  }
12029
12142
  async listProfiles() {
12030
- return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id, { requireAscendingIdentity: true });
12143
+ return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
12031
12144
  }
12032
12145
  async listProfilesPage(options = {}) {
12033
12146
  const normalized = normalizeBoundedReadOptions(options);
@@ -244,28 +244,6 @@ function truncateText(value, max = 80) {
244
244
  return text.slice(0, max);
245
245
  return `${text.slice(0, max - 3)}...`;
246
246
  }
247
- function summarizeConfig(config, opts = {}) {
248
- const summary = {
249
- id: config.id,
250
- slug: config.slug,
251
- name: config.name,
252
- category: config.category,
253
- agent: config.agent,
254
- kind: config.kind,
255
- format: config.format,
256
- target_path: config.target_path,
257
- output_count: config.outputs.length,
258
- version: config.version,
259
- is_template: config.is_template
260
- };
261
- if (opts.verbose) {
262
- summary.updated_at = config.updated_at;
263
- summary.description = config.description;
264
- summary.tags = config.tags;
265
- summary.outputs = config.outputs;
266
- }
267
- return summary;
268
- }
269
247
  function summarizeProfile(profile, opts = {}) {
270
248
  const selectorCount = (profile.selectors.os?.length ?? 0) + (profile.selectors.arch?.length ?? 0) + (profile.selectors.hostnames?.length ?? 0);
271
249
  const summary = {
@@ -2059,6 +2037,19 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
2059
2037
  const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
2060
2038
  return { ...page, source_bounded: false };
2061
2039
  }
2040
+ function projectBoundedPage(page, project) {
2041
+ return {
2042
+ items: page.items.map(project),
2043
+ total: page.total,
2044
+ limit: page.limit,
2045
+ cursor: page.cursor,
2046
+ next_cursor: page.next_cursor,
2047
+ has_more: page.has_more,
2048
+ complete: page.complete,
2049
+ truncated: page.truncated,
2050
+ source_bounded: page.source_bounded
2051
+ };
2052
+ }
2062
2053
 
2063
2054
  class CollectionChangedWhilePagingError extends Error {
2064
2055
  constructor(label, detail) {
@@ -2124,7 +2115,7 @@ function isNotFoundHttpError2(err) {
2124
2115
  var localStoreModulePromise = null;
2125
2116
  function localStoreModule() {
2126
2117
  if (!localStoreModulePromise)
2127
- localStoreModulePromise = import("./local-5wvv5xv3.js");
2118
+ localStoreModulePromise = import("./local-0a9gja58.js");
2128
2119
  return localStoreModulePromise;
2129
2120
  }
2130
2121
 
@@ -2138,6 +2129,15 @@ class LocalConfigStore {
2138
2129
  async listConfigs(filter) {
2139
2130
  return (await localStoreModule()).listConfigs(filter, this.db);
2140
2131
  }
2132
+ async listConfigsPage(filter = {}, options = {}) {
2133
+ return (await localStoreModule()).listConfigsPage(filter, options, this.db);
2134
+ }
2135
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
2136
+ return (await localStoreModule()).listConfigIdentitiesPage(filter, options, this.db);
2137
+ }
2138
+ async listConfigSummariesPage(filter = {}, options = {}) {
2139
+ return (await localStoreModule()).listConfigSummariesPage(filter, options, this.db);
2140
+ }
2141
2141
  async getConfig(idOrSlug) {
2142
2142
  return (await localStoreModule()).getConfig(idOrSlug, this.db);
2143
2143
  }
@@ -2241,6 +2241,43 @@ class LocalConfigStore {
2241
2241
  (await localStoreModule()).resetLocalDatabase();
2242
2242
  }
2243
2243
  }
2244
+ function toConfigIdentity(value) {
2245
+ const record = value && typeof value === "object" ? value : {};
2246
+ return {
2247
+ id: String(record.id ?? ""),
2248
+ name: String(record.name ?? ""),
2249
+ slug: String(record.slug ?? ""),
2250
+ kind: String(record.kind ?? ""),
2251
+ category: String(record.category ?? ""),
2252
+ agent: String(record.agent ?? ""),
2253
+ format: String(record.format ?? ""),
2254
+ is_template: Boolean(record.is_template),
2255
+ version: Number(record.version ?? 0),
2256
+ created_at: String(record.created_at ?? ""),
2257
+ updated_at: String(record.updated_at ?? ""),
2258
+ synced_at: record.synced_at == null ? null : String(record.synced_at)
2259
+ };
2260
+ }
2261
+ function toConfigSummary(value) {
2262
+ const record = value && typeof value === "object" ? value : {};
2263
+ const outputs = Array.isArray(record.outputs) ? record.outputs : [];
2264
+ return {
2265
+ id: String(record.id ?? ""),
2266
+ slug: String(record.slug ?? ""),
2267
+ name: String(record.name ?? ""),
2268
+ category: String(record.category ?? ""),
2269
+ agent: String(record.agent ?? ""),
2270
+ kind: String(record.kind ?? ""),
2271
+ format: String(record.format ?? ""),
2272
+ target_path: record.target_path == null ? null : String(record.target_path),
2273
+ output_count: Number(record.output_count ?? outputs.length),
2274
+ version: Number(record.version ?? 0),
2275
+ is_template: Boolean(record.is_template),
2276
+ ...record.updated_at !== undefined ? { updated_at: String(record.updated_at) } : {},
2277
+ ...record.description !== undefined ? { description: record.description == null ? null : String(record.description) } : {},
2278
+ ...Array.isArray(record.tags) ? { tags: record.tags.map(String) } : {}
2279
+ };
2280
+ }
2244
2281
 
2245
2282
  class CloudConfigStore {
2246
2283
  mode = "api";
@@ -2262,7 +2299,7 @@ class CloudConfigStore {
2262
2299
  throw err;
2263
2300
  }
2264
2301
  }
2265
- async listConfigsPageRemote(filter, options) {
2302
+ async listConfigsPage(filter = {}, options = {}) {
2266
2303
  const normalized = normalizeBoundedReadOptions(options);
2267
2304
  const params = new URLSearchParams;
2268
2305
  if (filter.category)
@@ -2273,13 +2310,67 @@ class CloudConfigStore {
2273
2310
  params.set("kind", filter.kind);
2274
2311
  if (filter.search)
2275
2312
  params.set("search", filter.search);
2313
+ for (const tag of filter.tags ?? [])
2314
+ params.append("tag", tag);
2276
2315
  params.set("limit", String(normalized.limit));
2277
2316
  params.set("cursor", String(normalized.cursor));
2278
2317
  const { data } = await this.request("GET", `/configs?${params.toString()}`);
2279
2318
  return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
2280
2319
  }
2320
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
2321
+ const normalized = normalizeBoundedReadOptions(options);
2322
+ const params = new URLSearchParams;
2323
+ if (filter.category)
2324
+ params.set("category", filter.category);
2325
+ if (filter.agent)
2326
+ params.set("agent", filter.agent);
2327
+ if (filter.kind)
2328
+ params.set("kind", filter.kind);
2329
+ if (filter.search)
2330
+ params.set("search", filter.search);
2331
+ for (const tag of filter.tags ?? [])
2332
+ params.append("tag", tag);
2333
+ params.set("view", "identity");
2334
+ params.set("limit", String(normalized.limit));
2335
+ params.set("cursor", String(normalized.cursor));
2336
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
2337
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config identity list");
2338
+ if (page.items.some((item) => {
2339
+ const record = item && typeof item === "object" ? item : {};
2340
+ return ["content", "target_path", "outputs", "description", "tags"].some((field) => Object.prototype.hasOwnProperty.call(record, field));
2341
+ })) {
2342
+ throw new Error("Instructions /v1 config identity projection is unavailable; deploy the identity endpoint before using compact lists");
2343
+ }
2344
+ return projectBoundedPage(page, toConfigIdentity);
2345
+ }
2346
+ async listConfigSummariesPage(filter = {}, options = {}) {
2347
+ const normalized = normalizeBoundedReadOptions(options);
2348
+ const params = new URLSearchParams;
2349
+ if (filter.category)
2350
+ params.set("category", filter.category);
2351
+ if (filter.agent)
2352
+ params.set("agent", filter.agent);
2353
+ if (filter.kind)
2354
+ params.set("kind", filter.kind);
2355
+ if (filter.search)
2356
+ params.set("search", filter.search);
2357
+ for (const tag of filter.tags ?? [])
2358
+ params.append("tag", tag);
2359
+ params.set("view", "summary");
2360
+ params.set("limit", String(normalized.limit));
2361
+ params.set("cursor", String(normalized.cursor));
2362
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
2363
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config summary list");
2364
+ if (page.items.some((item) => {
2365
+ const record = item && typeof item === "object" ? item : {};
2366
+ return Object.prototype.hasOwnProperty.call(record, "content") || Object.prototype.hasOwnProperty.call(record, "outputs");
2367
+ })) {
2368
+ throw new Error("Instructions /v1 config summary projection is unavailable; deploy the summary endpoint before using summary lists");
2369
+ }
2370
+ return projectBoundedPage(page, toConfigSummary);
2371
+ }
2281
2372
  async listConfigs(filter = {}) {
2282
- const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPageRemote(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
2373
+ const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPage(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
2283
2374
  let filtered = configs;
2284
2375
  if (filter.tags && filter.tags.length > 0) {
2285
2376
  filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
@@ -2345,7 +2436,7 @@ class CloudConfigStore {
2345
2436
  return data?.pruned ?? 0;
2346
2437
  }
2347
2438
  async listProfiles() {
2348
- return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id, { requireAscendingIdentity: true });
2439
+ return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
2349
2440
  }
2350
2441
  async listProfilesPage(options = {}) {
2351
2442
  const normalized = normalizeBoundedReadOptions(options);
@@ -7297,4 +7388,4 @@ function renderMachineAwareContentPreview(content, variables) {
7297
7388
  return isTemplate(content) ? renderTemplatePreview(content, variables) : { content, unresolved: [] };
7298
7389
  }
7299
7390
 
7300
- export { pagedPayload, summarizeConfig, summarizeProfile, summarizeApplyResult, normalizeBoundedReadOptions, boundedReadPage, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, getReportedDbPath, getRawStoreRoot, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, legacyProfileConfigBinding, normalizeProfileConfigBinding, hasInstructionsEnvAuthorityIntent, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, resolveConfigStore };
7391
+ export { pagedPayload, summarizeProfile, summarizeApplyResult, normalizeBoundedReadOptions, boundedReadPage, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, getReportedDbPath, getRawStoreRoot, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, legacyProfileConfigBinding, normalizeProfileConfigBinding, hasInstructionsEnvAuthorityIntent, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, resolveConfigStore };
@@ -5,7 +5,7 @@ import {
5
5
  expandPath,
6
6
  getConfigHome,
7
7
  normalizeTargetPath
8
- } from "./index-fwbs6tma.js";
8
+ } from "./index-ypcef3a2.js";
9
9
  import {
10
10
  applyTransform,
11
11
  detectMachineContext,
@@ -13,7 +13,7 @@ import {
13
13
  resolveConfigStore,
14
14
  retiredOrUnsupportedAgentReason,
15
15
  templateizeMachineContent
16
- } from "./index-4pfq42t5.js";
16
+ } from "./index-aj66f6xr.js";
17
17
  import {
18
18
  isSecretVarName,
19
19
  redactContent,
@@ -73,18 +73,20 @@ function createInstructionsS3ObjectStore(config, createClient = (options) => new
73
73
  return {
74
74
  async putIfAbsent(key, bytes, options) {
75
75
  assertSafeInstructionsObjectKey(key);
76
+ let credentials;
77
+ try {
78
+ credentials = resolveRequestCredentials(config);
79
+ } catch {
80
+ throw new Error("Instructions S3 conditional object creation failed");
81
+ }
76
82
  for (let attempt = 1;attempt <= CONDITIONAL_CREATE_ATTEMPTS; attempt += 1) {
77
83
  let response;
78
84
  const controller = new AbortController;
79
85
  try {
80
- const url = client.presign(key, { method: "PUT", expiresIn: 60 });
81
- response = await runWithDeadline(() => requestFetch(url, {
86
+ const signed = signConditionalCreateRequest(config, key, bytes, options.contentType, credentials, new Date);
87
+ response = await runWithDeadline(() => requestFetch(signed.url, {
82
88
  method: "PUT",
83
- headers: {
84
- "content-type": options.contentType,
85
- "content-md5": createHash("md5").update(bytes).digest("base64"),
86
- "if-none-match": "*"
87
- },
89
+ headers: signed.headers,
88
90
  body: Uint8Array.from(bytes),
89
91
  redirect: "error",
90
92
  signal: controller.signal
@@ -220,7 +222,7 @@ function resolveRequestCredentials(config) {
220
222
  const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY?.trim();
221
223
  const sessionToken = process.env.AWS_SESSION_TOKEN?.trim();
222
224
  if (!accessKeyId || !secretAccessKey) {
223
- throw new Error("Instructions S3 exact-version reads require explicit or AWS environment credentials");
225
+ throw new Error("Instructions S3 signed requests require explicit or AWS environment credentials");
224
226
  }
225
227
  return { accessKeyId, secretAccessKey, ...sessionToken ? { sessionToken } : {} };
226
228
  }
@@ -235,25 +237,43 @@ function signVersionedRequest(config, key, versionId, method, credentials, now)
235
237
  "x-amz-date": amzDate,
236
238
  ...credentials.sessionToken ? { "x-amz-security-token": credentials.sessionToken } : {}
237
239
  });
238
- const signedHeaderNames = [
239
- "host",
240
- "x-amz-content-sha256",
241
- "x-amz-date",
242
- ...credentials.sessionToken ? ["x-amz-security-token"] : []
243
- ].sort();
244
- const canonicalHeaders = signedHeaderNames.map((name) => `${name}:${headers.get(name).trim()}
245
- `).join("");
246
240
  const canonicalQuery = `versionId=${awsEncode(versionId)}`;
241
+ authorizeRequest(method, url, canonicalQuery, headers, EMPTY_SHA256, credentials, config.region, shortDate, amzDate);
242
+ return { url: url.toString(), headers };
243
+ }
244
+ function signConditionalCreateRequest(config, key, bytes, contentType, credentials, now) {
245
+ const url = buildObjectUrl(config, key);
246
+ const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
247
+ const shortDate = amzDate.slice(0, 8);
248
+ const payloadHash = createHash("sha256").update(bytes).digest("hex");
249
+ const headers = new Headers({
250
+ "content-md5": createHash("md5").update(bytes).digest("base64"),
251
+ "content-type": contentType,
252
+ host: url.host,
253
+ "if-none-match": "*",
254
+ "x-amz-content-sha256": payloadHash,
255
+ "x-amz-date": amzDate,
256
+ ...credentials.sessionToken ? { "x-amz-security-token": credentials.sessionToken } : {}
257
+ });
258
+ authorizeRequest("PUT", url, "", headers, payloadHash, credentials, config.region, shortDate, amzDate);
259
+ return { url: url.toString(), headers };
260
+ }
261
+ function authorizeRequest(method, url, canonicalQuery, headers, payloadHash, credentials, region, shortDate, amzDate) {
262
+ const signedHeaderNames = [];
263
+ headers.forEach((_value, name) => signedHeaderNames.push(name));
264
+ signedHeaderNames.sort();
265
+ const canonicalHeaders = signedHeaderNames.map((name) => `${name}:${headers.get(name).trim().replace(/\s+/g, " ")}
266
+ `).join("");
247
267
  const canonicalRequest = [
248
268
  method,
249
269
  url.pathname,
250
270
  canonicalQuery,
251
271
  canonicalHeaders,
252
272
  signedHeaderNames.join(";"),
253
- EMPTY_SHA256
273
+ payloadHash
254
274
  ].join(`
255
275
  `);
256
- const scope = `${shortDate}/${config.region}/s3/aws4_request`;
276
+ const scope = `${shortDate}/${region}/s3/aws4_request`;
257
277
  const stringToSign = [
258
278
  "AWS4-HMAC-SHA256",
259
279
  amzDate,
@@ -262,12 +282,11 @@ function signVersionedRequest(config, key, versionId, method, credentials, now)
262
282
  ].join(`
263
283
  `);
264
284
  const dateKey = hmac(`AWS4${credentials.secretAccessKey}`, shortDate);
265
- const regionKey = hmac(dateKey, config.region);
285
+ const regionKey = hmac(dateKey, region);
266
286
  const serviceKey = hmac(regionKey, "s3");
267
287
  const signingKey = hmac(serviceKey, "aws4_request");
268
288
  const signature = createHmac("sha256", signingKey).update(stringToSign).digest("hex");
269
289
  headers.set("authorization", `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${signedHeaderNames.join(";")}, Signature=${signature}`);
270
- return { url: url.toString(), headers };
271
290
  }
272
291
  function buildObjectUrl(config, key) {
273
292
  const encodedKey = key.split("/").map(awsEncode).join("/");
@@ -5,7 +5,7 @@ import {
5
5
  expandPath,
6
6
  getConfigHome,
7
7
  normalizeTargetPath
8
- } from "./index-z3ma4aqk.js";
8
+ } from "./index-r7nfef2g.js";
9
9
  import {
10
10
  applyTransform,
11
11
  detectMachineContext,
@@ -16,7 +16,7 @@ import {
16
16
  resolveConfigStore,
17
17
  retiredOrUnsupportedAgentReason,
18
18
  templateizeMachineContent
19
- } from "./index-7m4j8a33.js";
19
+ } from "./index-6jncnnw7.js";
20
20
 
21
21
  // src/lib/sync.ts
22
22
  import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
@@ -18,7 +18,7 @@ import {
18
18
  resolveProfileVariables,
19
19
  scanSecrets,
20
20
  stampCursorGlobalAuthorityMarker
21
- } from "./index-7m4j8a33.js";
21
+ } from "./index-6jncnnw7.js";
22
22
  import {
23
23
  ConfigApplyError,
24
24
  parseTemplateVars
@@ -15,7 +15,7 @@ import {
15
15
  resolveConfigStore,
16
16
  resolveProfileVariables,
17
17
  stampCursorGlobalAuthorityMarker
18
- } from "./index-4pfq42t5.js";
18
+ } from "./index-aj66f6xr.js";
19
19
  import {
20
20
  isSecretVarName,
21
21
  redactFormatForTarget,