@lambdacurry/arbor 0.14.0 → 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 +298 -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),
@@ -1864,6 +1910,23 @@ var apps = sqliteTable("apps", {
1864
1910
  spaceIdx: index("apps_space_idx").on(t.spaceId, t.lifecycle, t.createdAt),
1865
1911
  orgIdx: index("apps_org_idx").on(t.orgId, t.access, t.discovery)
1866
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
+ }));
1867
1930
  var appDeployments = sqliteTable("app_deployments", {
1868
1931
  id: text("id").primaryKey(),
1869
1932
  appId: text("app_id").notNull().references(() => apps.id),
@@ -2049,6 +2112,19 @@ var PREVIEW_MIME_TYPES = new Set([
2049
2112
  // ../core/src/ops/app.ts
2050
2113
  var APP_MAX_MODULE_BYTES = 10 * 1024 * 1024;
2051
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");
2052
2128
  // ../core/src/queries/lane-match.ts
2053
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(" "));
2054
2130
  // ../core/src/queries/activity.ts
@@ -16714,6 +16790,31 @@ var app2 = exports_external.looseObject({
16714
16790
  url: exports_external.string().optional()
16715
16791
  });
16716
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
+ ]);
16717
16818
  var treeThread = exports_external.looseObject({
16718
16819
  id,
16719
16820
  title: exports_external.string(),
@@ -16995,6 +17096,30 @@ var MCP_OUTPUT_SCHEMAS = {
16995
17096
  status: exports_external.literal("deleted"),
16996
17097
  retrievalTier: exports_external.string()
16997
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
+ }),
16998
17123
  app_list: exports_external.object({ result: exports_external.array(app2) }),
16999
17124
  app_get: exports_external.looseObject({
17000
17125
  app: app2,
@@ -17271,6 +17396,7 @@ var MCP_TOOL_ANNOTATIONS = {
17271
17396
  artifact_get: readOnly,
17272
17397
  artifact_transition: additive,
17273
17398
  artifact_delete: destructive,
17399
+ secrets: destructive,
17274
17400
  app_get: readOnly,
17275
17401
  app_list: readOnly,
17276
17402
  app_deployment_get: readOnly,
@@ -18843,6 +18969,178 @@ var ACTION_DEFINITIONS = [
18843
18969
  toolset: "artifacts",
18844
18970
  run: (ex, input) => ex.call("artifact.transition", { ...input, to: "deleted" })
18845
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
+ },
18846
19144
  {
18847
19145
  name: "apps",
18848
19146
  title: "List visible Apps",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.14.0",
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",