@lambdacurry/arbor 0.13.10 → 0.14.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 (2) hide show
  1. package/dist/arbor.js +313 -0
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1801,6 +1801,52 @@ var artifactVersions = sqliteTable("artifact_versions", {
1801
1801
  }, (t) => ({
1802
1802
  artifactVersionUq: uniqueIndex("artifact_versions_artifact_version_uq").on(t.artifactId, t.version)
1803
1803
  }));
1804
+ var secrets = sqliteTable("secrets", {
1805
+ id: text("id").primaryKey(),
1806
+ orgId: text("org_id").notNull().references(() => orgs.id),
1807
+ name: text("name").notNull(),
1808
+ description: text("description").notNull().default(""),
1809
+ lifecycle: text("lifecycle").$type().notNull().default("active"),
1810
+ currentVersionId: text("current_version_id"),
1811
+ currentVersion: integer("current_version").notNull().default(0),
1812
+ metadataRevision: integer("metadata_revision").notNull().default(0),
1813
+ createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
1814
+ createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
1815
+ createdAt: ts("created_at").notNull(),
1816
+ revokedAt: ts("revoked_at")
1817
+ }, (t) => ({
1818
+ orgNameUq: uniqueIndex("secrets_org_name_uq").on(t.orgId, t.name),
1819
+ orgLifecycleIdx: index("secrets_org_lifecycle_idx").on(t.orgId, t.lifecycle, t.createdAt)
1820
+ }));
1821
+ var secretVersions = sqliteTable("secret_versions", {
1822
+ id: text("id").primaryKey(),
1823
+ secretId: text("secret_id").notNull().references(() => secrets.id),
1824
+ version: integer("version").notNull(),
1825
+ ciphertext: text("ciphertext").notNull(),
1826
+ iv: text("iv").notNull(),
1827
+ keyId: text("key_id").notNull(),
1828
+ algorithm: text("algorithm").notNull().default("AES-GCM-256"),
1829
+ createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
1830
+ createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
1831
+ createdAt: ts("created_at").notNull()
1832
+ }, (t) => ({
1833
+ secretVersionUq: uniqueIndex("secret_versions_secret_version_uq").on(t.secretId, t.version)
1834
+ }));
1835
+ var secretGrants = sqliteTable("secret_grants", {
1836
+ id: text("id").primaryKey(),
1837
+ orgId: text("org_id").notNull().references(() => orgs.id),
1838
+ secretId: text("secret_id").references(() => secrets.id),
1839
+ scopeKey: text("scope_key").notNull(),
1840
+ profileId: text("profile_id").notNull().references(() => profiles.id),
1841
+ permissions: text("permissions", { mode: "json" }).$type().notNull(),
1842
+ grantedByProfileId: text("granted_by_profile_id").notNull().references(() => profiles.id),
1843
+ grantedExecutionContextId: text("granted_execution_context_id").notNull().references(() => executionContexts.id),
1844
+ createdAt: ts("created_at").notNull(),
1845
+ updatedAt: ts("updated_at").notNull()
1846
+ }, (t) => ({
1847
+ scopeProfileUq: uniqueIndex("secret_grants_scope_profile_uq").on(t.orgId, t.scopeKey, t.profileId),
1848
+ profileIdx: index("secret_grants_profile_idx").on(t.profileId, t.orgId)
1849
+ }));
1804
1850
  var appBundles = sqliteTable("app_bundles", {
1805
1851
  id: text("id").primaryKey(),
1806
1852
  artifactVersionId: text("artifact_version_id").notNull().references(() => artifactVersions.id),
@@ -1838,6 +1884,7 @@ var apps = sqliteTable("apps", {
1838
1884
  orgId: text("org_id").notNull().references(() => orgs.id),
1839
1885
  spaceId: text("space_id").notNull().references(() => spaces.id),
1840
1886
  title: text("title").notNull(),
1887
+ description: text("description").notNull().default(""),
1841
1888
  slug: text("slug").notNull(),
1842
1889
  lifecycle: text("lifecycle").$type().notNull().default("active"),
1843
1890
  access: text("access").$type().notNull(),
@@ -1863,6 +1910,23 @@ var apps = sqliteTable("apps", {
1863
1910
  spaceIdx: index("apps_space_idx").on(t.spaceId, t.lifecycle, t.createdAt),
1864
1911
  orgIdx: index("apps_org_idx").on(t.orgId, t.access, t.discovery)
1865
1912
  }));
1913
+ var secretBindings = sqliteTable("secret_bindings", {
1914
+ id: text("id").primaryKey(),
1915
+ secretId: text("secret_id").notNull().references(() => secrets.id),
1916
+ targetType: text("target_type").notNull().default("app"),
1917
+ appId: text("app_id").notNull().references(() => apps.id),
1918
+ bindingName: text("binding_name").notNull(),
1919
+ status: text("status").$type().notNull().default("active"),
1920
+ createdByProfileId: text("created_by_profile_id").notNull().references(() => profiles.id),
1921
+ createdExecutionContextId: text("created_execution_context_id").notNull().references(() => executionContexts.id),
1922
+ createdAt: ts("created_at").notNull(),
1923
+ updatedByProfileId: text("updated_by_profile_id").notNull().references(() => profiles.id),
1924
+ updatedExecutionContextId: text("updated_execution_context_id").notNull().references(() => executionContexts.id),
1925
+ updatedAt: ts("updated_at").notNull()
1926
+ }, (t) => ({
1927
+ appNameUq: uniqueIndex("secret_bindings_app_name_uq").on(t.appId, t.bindingName),
1928
+ secretIdx: index("secret_bindings_secret_idx").on(t.secretId, t.status)
1929
+ }));
1866
1930
  var appDeployments = sqliteTable("app_deployments", {
1867
1931
  id: text("id").primaryKey(),
1868
1932
  appId: text("app_id").notNull().references(() => apps.id),
@@ -2048,6 +2112,19 @@ var PREVIEW_MIME_TYPES = new Set([
2048
2112
  // ../core/src/ops/app.ts
2049
2113
  var APP_MAX_MODULE_BYTES = 10 * 1024 * 1024;
2050
2114
  var APP_MAX_ASSET_BYTES = 25 * 1024 * 1024;
2115
+ // ../core/src/ops/secret.ts
2116
+ var SECRET_PERMISSIONS = [
2117
+ "create",
2118
+ "metadata:read",
2119
+ "value:write",
2120
+ "rotate",
2121
+ "bind",
2122
+ "unbind",
2123
+ "revoke",
2124
+ "delete",
2125
+ "plaintext:read"
2126
+ ];
2127
+ var SECRET_ADMIN_PERMISSIONS = SECRET_PERMISSIONS.filter((permission) => permission !== "create" && permission !== "plaintext:read");
2051
2128
  // ../core/src/queries/lane-match.ts
2052
2129
  var STOP_WORDS = new Set("a an and are as at be by for from has have here how i in is it me of on or our the their they this to was what when where which who will with you your".split(" "));
2053
2130
  // ../core/src/queries/activity.ts
@@ -16713,6 +16790,31 @@ var app2 = exports_external.looseObject({
16713
16790
  url: exports_external.string().optional()
16714
16791
  });
16715
16792
  var deployment = exports_external.looseObject({ id, appId: id, bundleId: id, status: exports_external.string() });
16793
+ var secretMetadata = exports_external.looseObject({
16794
+ id,
16795
+ orgId: id,
16796
+ name: exports_external.string(),
16797
+ description: exports_external.string(),
16798
+ lifecycle: exports_external.enum(["active", "revoked"]),
16799
+ currentVersionId: nullableString,
16800
+ currentVersion: exports_external.number().int().min(0),
16801
+ metadataRevision: exports_external.number().int().min(0),
16802
+ createdByProfileId: id,
16803
+ createdExecutionContextId: id,
16804
+ createdAt: timestamp,
16805
+ revokedAt: nullableString
16806
+ });
16807
+ var secretPermission = exports_external.enum([
16808
+ "create",
16809
+ "metadata:read",
16810
+ "value:write",
16811
+ "rotate",
16812
+ "bind",
16813
+ "unbind",
16814
+ "revoke",
16815
+ "delete",
16816
+ "plaintext:read"
16817
+ ]);
16716
16818
  var treeThread = exports_external.looseObject({
16717
16819
  id,
16718
16820
  title: exports_external.string(),
@@ -16994,6 +17096,30 @@ var MCP_OUTPUT_SCHEMAS = {
16994
17096
  status: exports_external.literal("deleted"),
16995
17097
  retrievalTier: exports_external.string()
16996
17098
  }),
17099
+ secrets: exports_external.looseObject({
17100
+ result: exports_external.array(secretMetadata).optional(),
17101
+ secret: secretMetadata.optional(),
17102
+ bindings: exports_external.array(exports_external.looseObject({
17103
+ id,
17104
+ targetType: exports_external.literal("app"),
17105
+ appId: id,
17106
+ bindingName: exports_external.string(),
17107
+ status: exports_external.enum(["active", "unbound"]),
17108
+ updatedAt: timestamp
17109
+ })).optional(),
17110
+ grants: exports_external.array(exports_external.looseObject({ profileId: id, permissions: exports_external.array(secretPermission) })).optional(),
17111
+ id: id.optional(),
17112
+ secretId: id.nullable().optional(),
17113
+ version: exports_external.number().int().min(1).optional(),
17114
+ rotated: exports_external.boolean().optional(),
17115
+ profileId: id.optional(),
17116
+ permissions: exports_external.array(secretPermission).optional(),
17117
+ revoked: exports_external.boolean().optional(),
17118
+ targetType: exports_external.literal("app").optional(),
17119
+ appId: id.optional(),
17120
+ bindingName: exports_external.string().optional(),
17121
+ unbound: exports_external.boolean().optional()
17122
+ }),
16997
17123
  app_list: exports_external.object({ result: exports_external.array(app2) }),
16998
17124
  app_get: exports_external.looseObject({
16999
17125
  app: app2,
@@ -17270,6 +17396,7 @@ var MCP_TOOL_ANNOTATIONS = {
17270
17396
  artifact_get: readOnly,
17271
17397
  artifact_transition: additive,
17272
17398
  artifact_delete: destructive,
17399
+ secrets: destructive,
17273
17400
  app_get: readOnly,
17274
17401
  app_list: readOnly,
17275
17402
  app_deployment_get: readOnly,
@@ -18842,6 +18969,178 @@ var ACTION_DEFINITIONS = [
18842
18969
  toolset: "artifacts",
18843
18970
  run: (ex, input) => ex.call("artifact.transition", { ...input, to: "deleted" })
18844
18971
  },
18972
+ {
18973
+ name: "secrets",
18974
+ title: "Manage encrypted Secrets",
18975
+ description: "Create, authorize, version, rotate, bind, and revoke first-class Arbor Secrets without revealing plaintext. set and rotate never echo submitted values; bind exposes the current version only to the named App runtime binding, while identity administration and runtime consumption remain separate. Plaintext reveal is not shipped in v1.",
18976
+ inputSchema: {
18977
+ verb: exports_external.enum([
18978
+ "list",
18979
+ "get",
18980
+ "create",
18981
+ "set",
18982
+ "rotate",
18983
+ "grant",
18984
+ "revoke_grant",
18985
+ "bind",
18986
+ "unbind",
18987
+ "revoke"
18988
+ ]).describe("which Secret operation to perform"),
18989
+ secretId: exports_external.string().optional().describe("Secret id; omit only when granting/revoking org-scoped create permission"),
18990
+ name: exports_external.string().optional().describe("create: lowercase Secret name"),
18991
+ description: exports_external.string().max(500).optional().describe("create: non-sensitive purpose"),
18992
+ value: exports_external.string().min(1).optional().describe("set/rotate: plaintext submitted once and never returned or recorded"),
18993
+ profileId: exports_external.string().optional().describe("grant/revoke_grant: authorized human or agent"),
18994
+ permissions: exports_external.array(exports_external.enum([
18995
+ "create",
18996
+ "metadata:read",
18997
+ "value:write",
18998
+ "rotate",
18999
+ "bind",
19000
+ "unbind",
19001
+ "revoke",
19002
+ "delete",
19003
+ "plaintext:read"
19004
+ ])).optional().describe("grant: explicit permissions; plaintext:read is reserved for a future dedicated reveal path and normal grants reject it"),
19005
+ appId: exports_external.string().optional().describe("bind: target App, app_…"),
19006
+ bindingName: exports_external.string().optional().describe("bind: uppercase Dynamic Worker env binding, e.g. API_TOKEN"),
19007
+ bindingId: exports_external.string().optional().describe("unbind: binding id, sbd_…")
19008
+ },
19009
+ surfaces: ["mcp"],
19010
+ toolset: "apps",
19011
+ run: dispatch({
19012
+ list: "secret.list",
19013
+ get: "secret.get",
19014
+ create: "secret.create",
19015
+ set: "secret.set",
19016
+ rotate: "secret.rotate",
19017
+ grant: "secret.grant",
19018
+ revoke_grant: "secret.revoke_grant",
19019
+ bind: "secret.bind",
19020
+ unbind: "secret.unbind",
19021
+ revoke: "secret.revoke"
19022
+ })
19023
+ },
19024
+ {
19025
+ name: "secret_list",
19026
+ title: "List authorized Secrets",
19027
+ description: "List only Secret metadata the current identity may read. Values, ciphertext, and encryption metadata are never projected.",
19028
+ inputSchema: {},
19029
+ surfaces: ["cli"],
19030
+ toolset: "apps",
19031
+ run: forward("secret.list")
19032
+ },
19033
+ {
19034
+ name: "secret_get",
19035
+ title: "Read Secret metadata",
19036
+ description: "Read one Secret's lifecycle, current version number, identity grants, and App bindings. This never returns plaintext, ciphertext, IVs, or key identifiers.",
19037
+ inputSchema: { secretId: exports_external.string().describe("the Secret, sec_…") },
19038
+ surfaces: ["cli"],
19039
+ toolset: "apps",
19040
+ run: forward("secret.get")
19041
+ },
19042
+ {
19043
+ name: "secret_create",
19044
+ title: "Create a Secret",
19045
+ description: "Create first-class Secret metadata without material; an Org owner/admin or identity with org-scoped create permission may do this. Follow with secret_set to write its first encrypted version.",
19046
+ inputSchema: {
19047
+ name: exports_external.string().min(1).max(63).describe("lowercase stable name"),
19048
+ description: exports_external.string().max(500).optional().describe("non-sensitive purpose")
19049
+ },
19050
+ surfaces: ["cli"],
19051
+ toolset: "apps",
19052
+ run: forward("secret.create")
19053
+ },
19054
+ {
19055
+ name: "secret_set",
19056
+ title: "Set a Secret value",
19057
+ description: "Write the first encrypted SecretVersion. The submitted value is never echoed, logged, audited, or placed in provenance; use secret_rotate after the first version.",
19058
+ inputSchema: {
19059
+ secretId: exports_external.string().describe("the empty Secret, sec_…"),
19060
+ value: exports_external.string().min(1).describe("plaintext submitted once and never returned")
19061
+ },
19062
+ surfaces: ["cli"],
19063
+ toolset: "apps",
19064
+ run: forward("secret.set")
19065
+ },
19066
+ {
19067
+ name: "secret_rotate",
19068
+ title: "Rotate a Secret value",
19069
+ description: "Append a new encrypted SecretVersion and make every active App binding consume it. Rotation permission is independent of value-write, bind, and plaintext-read permission; the submitted value is never returned.",
19070
+ inputSchema: {
19071
+ secretId: exports_external.string().describe("the active Secret, sec_…"),
19072
+ value: exports_external.string().min(1).describe("new plaintext submitted once and never returned")
19073
+ },
19074
+ surfaces: ["cli"],
19075
+ toolset: "apps",
19076
+ run: forward("secret.rotate")
19077
+ },
19078
+ {
19079
+ name: "secret_grant",
19080
+ title: "Grant Secret access",
19081
+ description: "Replace one human or agent's explicit Secret permissions; omit secretId only to grant org-scoped create. Plaintext-read is reserved for a future dedicated reveal path and this command rejects it; runtime App consumption is controlled by bindings, not this identity grant.",
19082
+ inputSchema: {
19083
+ secretId: exports_external.string().optional().describe("Secret scope; omit only for org-scoped create permission"),
19084
+ profileId: exports_external.string().describe("authorized human or agent profile"),
19085
+ permissions: exports_external.array(exports_external.enum([
19086
+ "create",
19087
+ "metadata:read",
19088
+ "value:write",
19089
+ "rotate",
19090
+ "bind",
19091
+ "unbind",
19092
+ "revoke",
19093
+ "delete",
19094
+ "plaintext:read"
19095
+ ]))
19096
+ },
19097
+ surfaces: ["cli"],
19098
+ toolset: "apps",
19099
+ run: forward("secret.grant")
19100
+ },
19101
+ {
19102
+ name: "secret_revoke_grant",
19103
+ title: "Revoke Secret access",
19104
+ description: "Remove one human or agent's explicit Secret grant. This changes administration authority only; an App binding remains a separate runtime-consumption grant.",
19105
+ inputSchema: {
19106
+ secretId: exports_external.string().optional().describe("Secret scope; omit for org create permission"),
19107
+ profileId: exports_external.string().describe("human or agent profile")
19108
+ },
19109
+ surfaces: ["cli"],
19110
+ toolset: "apps",
19111
+ run: forward("secret.revoke_grant")
19112
+ },
19113
+ {
19114
+ name: "secret_bind",
19115
+ title: "Bind a Secret to an App",
19116
+ description: "Authorize one App workload to consume the active Secret version through a provider-native Dynamic Worker env binding. The actor needs Secret bind authority and access to the App's Space. Binding permission never grants plaintext read to the acting identity, and no material enters bundles, deployments, receipts, or Events.",
19117
+ inputSchema: {
19118
+ secretId: exports_external.string().describe("active Secret with a value, sec_…"),
19119
+ appId: exports_external.string().describe("target App, app_…"),
19120
+ bindingName: exports_external.string().describe("uppercase runtime name, e.g. API_TOKEN")
19121
+ },
19122
+ surfaces: ["cli"],
19123
+ toolset: "apps",
19124
+ run: forward("secret.bind")
19125
+ },
19126
+ {
19127
+ name: "secret_unbind",
19128
+ title: "Unbind an App Secret",
19129
+ description: "Remove one App workload's runtime consumption binding without revoking the Secret or changing identity administration grants. Read secret_get for the binding id.",
19130
+ inputSchema: { bindingId: exports_external.string().describe("the App binding, sbd_…") },
19131
+ surfaces: ["cli"],
19132
+ toolset: "apps",
19133
+ run: forward("secret.unbind")
19134
+ },
19135
+ {
19136
+ name: "secret_revoke",
19137
+ title: "Revoke a Secret",
19138
+ description: "Move a Secret to revoked so every active workload binding fails closed while durable metadata, encrypted versions, attribution, and audit history remain. Permanent deletion and plaintext reveal are not shipped in v1.",
19139
+ inputSchema: { secretId: exports_external.string().describe("the Secret, sec_…") },
19140
+ surfaces: ["cli"],
19141
+ toolset: "apps",
19142
+ run: forward("secret.revoke")
19143
+ },
18845
19144
  {
18846
19145
  name: "apps",
18847
19146
  title: "List visible Apps",
@@ -18880,6 +19179,7 @@ var ACTION_DEFINITIONS = [
18880
19179
  inputSchema: {
18881
19180
  spaceId: exports_external.string().describe("owning Space, spc_…"),
18882
19181
  title: exports_external.string().min(1).max(160).describe("short factual App title"),
19182
+ description: exports_external.string().min(1).max(200).describe("one line of what this App is for, read by whoever is deciding whether to open it — not a changelog and not the source Artifact's summary"),
18883
19183
  slug: exports_external.string().min(1).max(59).describe("stable DNS label used by app-<slug>.arborthreads.dev"),
18884
19184
  access: exports_external.enum(["space", "public"]).describe("space requires membership; public is anonymous at the gateway"),
18885
19185
  discovery: exports_external.enum(["unlisted", "listed"]).nullable().optional().describe("public Apps only; default unlisted"),
@@ -18981,6 +19281,19 @@ var ACTION_DEFINITIONS = [
18981
19281
  toolset: "apps",
18982
19282
  run: forward("app.rollback")
18983
19283
  },
19284
+ {
19285
+ name: "app_update",
19286
+ title: "Edit an App's title or description",
19287
+ description: "Change the human-facing metadata a reader sees before opening an App. The description is the one line that answers 'what is this for'; keep it factual and current, because the directory and the App page both lead with it. Slug is deliberately not editable — the URL is the App's stable identity. Access, lifecycle, release, and state each have their own operation.",
19288
+ inputSchema: {
19289
+ appId: exports_external.string().describe("target App, app_…"),
19290
+ title: exports_external.string().min(1).max(160).optional().describe("short factual App title"),
19291
+ description: exports_external.string().min(1).max(200).optional().describe("one line of what this App is for")
19292
+ },
19293
+ surfaces: ["cli"],
19294
+ toolset: "apps",
19295
+ run: forward("app.update")
19296
+ },
18984
19297
  {
18985
19298
  name: "app_set_access",
18986
19299
  title: "Change App access",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.13.10",
3
+ "version": "0.14.1",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",