wicked-crew-api-types 0.173.0 → 0.178.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.
Files changed (2) hide show
  1. package/index.d.ts +585 -15
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -12311,9 +12311,12 @@ export interface PutDeliveryFreezeBody {
12311
12311
 
12312
12312
  /**
12313
12313
  * How crew reaches an upstream: an MCP server over stdio or streamable HTTP, or a plain REST API
12314
- * wrapped as tools from its OpenAPI document (`rest`, api-types 0.64.0).
12314
+ * wrapped as tools from its OpenAPI document (`rest`, api-types 0.64.0). (api-types 0.175.0,
12315
+ * DES-APPS-001 §5.1) `sql` (drivers `postgres`, `mysql`, `sqlite`) and `graphql` are Apps data
12316
+ * sources: registered through the same preview/save, but with NO tools — nothing of theirs is ever
12317
+ * offered to a governed run. Their preview answers {@link McpPreviewResponse.source} (the catalog).
12315
12318
  */
12316
- export type McpUpstreamKind = 'mcp-stdio' | 'mcp-http' | 'rest';
12319
+ export type McpUpstreamKind = 'mcp-stdio' | 'mcp-http' | 'rest' | 'sql' | 'graphql';
12317
12320
  /**
12318
12321
  * A tool's class, from its own `tools/list` annotations (never from a carrier): `read` when
12319
12322
  * `readOnlyHint` is true; else `destructive` unless `destructiveHint` is false; else `write`. A tool
@@ -12354,6 +12357,29 @@ export interface McpAuthConfig {
12354
12357
  prefix?: string;
12355
12358
  }
12356
12359
 
12360
+ /**
12361
+ * (api-types 0.174.0, DES-APPS-001 §5.2) The ranges the person confirmed for one server's (or
12362
+ * source's) connections. Every connection crew makes to it goes through ONE dialer that resolves
12363
+ * the host once, checks EVERY address, connects to the checked address (keeping the name for TLS)
12364
+ * and refuses redirects. With nothing confirmed, only global unicast addresses are reached, over
12365
+ * TLS. A loopback or private address is reached only when a range here covers it. `0.0.0.0/8`,
12366
+ * link-local (`169.254.0.0/16`, which holds `169.254.169.254`), CGNAT (`100.64.0.0/10`),
12367
+ * `fd00:ec2::254`, multicast, documentation and reserved ranges are always refused and cannot be
12368
+ * confirmed. An IPv4-mapped IPv6 address is judged as its IPv4 address.
12369
+ */
12370
+ export interface McpAddressPolicy {
12371
+ /**
12372
+ * CIDR ranges wholly inside loopback (`127.0.0.0/8`, `::1/128`) or a private range
12373
+ * (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fc00::/7`); at most 16. Anything else is a 400.
12374
+ */
12375
+ allow: string[];
12376
+ /**
12377
+ * Plaintext (`http:`) is accepted on a confirmed PRIVATE range. Loopback never needs it; a global
12378
+ * address never gets it. `false`/absent = TLS only.
12379
+ */
12380
+ plaintext?: boolean;
12381
+ }
12382
+
12357
12383
  /**
12358
12384
  * `POST /mcp/servers/preview`. `mcp-stdio` takes `command` (+ `args`); `mcp-http` takes `url`.
12359
12385
  * `rest` takes `url`, the base URL every call of the API is pinned to (its scheme, host and port,
@@ -12375,6 +12401,28 @@ export interface McpServerConfigBody {
12375
12401
  openapi?: Record<string, unknown>;
12376
12402
  /** `rest` only: the operations to wrap, by `operationId` or tool name; absent = all. */
12377
12403
  operations?: string[];
12404
+ /**
12405
+ * (api-types 0.174.0, DES-APPS-001 §5.2) `mcp-http` and `rest` only (a 400 on `mcp-stdio`, a
12406
+ * local program outside the dialer): the loopback/private ranges this server's connections may
12407
+ * reach. The preview already dials under it, so a preview of a server whose host is loopback or
12408
+ * private without a range covering it is a 409 `address_unconfirmed` naming the range to confirm
12409
+ * (`address_refused` for an always-refused address, `plaintext_refused` for http where TLS is
12410
+ * required). A non-empty `allow`, or
12411
+ * `plaintext: true`, is a human operator's only, at the preview and at the save (else 403
12412
+ * `address_confirm_human_only`), and the save audits it `mcp.server.address_confirmed`.
12413
+ */
12414
+ address?: McpAddressPolicy;
12415
+ /**
12416
+ * (api-types 0.175.0, DES-APPS-001 §5.1) `sql` only: the driver and its connection settings. The
12417
+ * password is the secret behind `auth.ref` (`auth` takes only `ref` for `sql`). `sqlite` sources come
12418
+ * from `POST /apps/uploads` (a snapshot digest), not from a preview.
12419
+ */
12420
+ sql?: SqlSourceConfigBody;
12421
+ /**
12422
+ * (api-types 0.175.0) `sql` only: the views (and materialized views) a read may name, as
12423
+ * `schema.view` (MySQL `database.view`). A view not listed is refused by the read policy.
12424
+ */
12425
+ viewsAllowed?: string[];
12378
12426
  /**
12379
12427
  * The secret VALUE this server's keychain entry will hold (wicked-crew#719). The preview is
12380
12428
  * probed with it and it is held with the preview; `POST /mcp/servers` writes it to the OS store
@@ -12453,6 +12501,30 @@ export interface McpServer {
12453
12501
  openapiUrl?: string | null;
12454
12502
  /** `rest` only: the operations that were picked; `null` = all. */
12455
12503
  operations?: string[] | null;
12504
+ /** (api-types 0.175.0) `sql` only: driver and connection settings (`ca` shown as whether one is set). */
12505
+ sql?: SqlSourceView;
12506
+ /** (api-types 0.175.0) `sql` only: views a read may name. */
12507
+ viewsAllowed?: string[];
12508
+ /**
12509
+ * (api-types 0.175.0, DES-APPS-001 §7.4) Postgres `sql` only: the per-source **Allow writes**
12510
+ * switch, `false` on every new source. Only a human operator turns it on or off
12511
+ * (`PUT /sources/:name/allow-writes`); turning it off withdraws every row-write grant on the
12512
+ * source. It is not part of the connection descriptor: reads are unaffected.
12513
+ */
12514
+ allowWrites?: boolean;
12515
+ /**
12516
+ * (api-types 0.175.0) `sql`/`graphql`: the sha256 of the source's connection descriptor (driver,
12517
+ * host, port, database, login, TLS mode, url, auth header, snapshot, confirmed ranges; never
12518
+ * `allowWrites`). Queries, actions and grants bind to it.
12519
+ */
12520
+ descriptorHash?: string;
12521
+ /**
12522
+ * (api-types 0.174.0) `mcp-http` and `rest` only: the ranges confirmed for this server's
12523
+ * connections. A server saved before 0.174.0 shows what crew re-derived for it: the IP literal or
12524
+ * `localhost` it was registered at; a private host NAME is not re-derived, and its calls are
12525
+ * refused until it is saved again with a range.
12526
+ */
12527
+ address?: McpAddressPolicy;
12456
12528
  authState: McpAuthState;
12457
12529
  enabled: boolean;
12458
12530
  health: McpHealth;
@@ -12534,7 +12606,17 @@ export interface McpPreviewResponse {
12534
12606
  auth: McpAuthConfig | null;
12535
12607
  openapiUrl?: string | null;
12536
12608
  operations?: string[] | null;
12609
+ /** (api-types 0.174.0) `mcp-http` and `rest` only: the ranges this preview dialled under. */
12610
+ address?: McpAddressPolicy;
12611
+ /** (api-types 0.175.0) `sql` only. */
12612
+ sql?: SqlSourceView;
12613
+ viewsAllowed?: string[];
12537
12614
  };
12615
+ /**
12616
+ * (api-types 0.175.0, DES-APPS-001 §5.1) `sql`/`graphql` only: what the describe found —
12617
+ * structure, never a value from a row — and, for Postgres, the login's privilege report.
12618
+ */
12619
+ source?: { catalog: SourceCatalog; privileges?: SourcePrivilegeReport };
12538
12620
  serverInfo: { name: string; version: string } | null;
12539
12621
  tools: McpPreviewTool[];
12540
12622
  diff: McpToolDiff | null;
@@ -12570,8 +12652,8 @@ export interface SaveMcpServerBody {
12570
12652
  /**
12571
12653
  * (api-types 0.112.0, G2) The operator naming the exact origin a `rest` server's calls go to
12572
12654
  * (`McpPreviewResponse.egress.origin`). Required when the preview's `egress.confirmRequired`
12573
- * (the base URL matches none of the document's `servers`, or its host is a loopback or private
12574
- * address, or did not resolve); without it, or with any other value, the save is a 409 `egress_unconfirmed`. It is
12655
+ * (the base URL matches none of the document's `servers`; since 0.174.0 a loopback or private
12656
+ * host is confirmed as a range in the config's `address` instead); without it, or with any other value, the save is a 409 `egress_unconfirmed`. It is
12575
12657
  * remembered with the server, so re-saving over the same origin does not ask again. Human
12576
12658
  * operator only (403 `egress_confirm_human_only`); audited `mcp.server.egress_confirmed`. A 400
12577
12659
  * `egress_not_rest` for a server that is not `rest`.
@@ -12596,16 +12678,21 @@ export interface McpRestEgress {
12596
12678
  servers: string[];
12597
12679
  /** The origin is one server's and the base path is that server's path or under it. */
12598
12680
  matches: boolean;
12599
- /** The host is `localhost`, or is or resolves to a loopback/private/link-local/unique-local address. */
12681
+ /**
12682
+ * The host is a loopback or private address (since api-types 0.174.0 always one the preview's
12683
+ * `address` confirmed: an unconfirmed one fails the preview, and an always-refused one, like
12684
+ * link-local or CGNAT, can never be confirmed).
12685
+ */
12600
12686
  privateAddress: boolean;
12601
12687
  /**
12602
- * `false` = the host is a name that did not resolve at preview, so crew could not check that it
12603
- * is not private. An IP literal is always `true`.
12688
+ * Since api-types 0.174.0 always `true`: a host that does not resolve fails the preview, because
12689
+ * the dialer cannot check where it goes.
12604
12690
  */
12605
12691
  resolved: boolean;
12606
12692
  /**
12607
- * `!matches || privateAddress || !resolved`, unless this origin was already confirmed for this
12608
- * server by an earlier save: the save needs `allowOrigin`.
12693
+ * `!matches`, unless this origin was already confirmed for this server by an earlier save: the
12694
+ * save needs `allowOrigin`. (Before api-types 0.174.0 a private or unresolved host needed it too;
12695
+ * addresses are now confirmed as ranges, in the config's `address`.)
12609
12696
  */
12610
12697
  confirmRequired: boolean;
12611
12698
  }
@@ -13012,6 +13099,248 @@ export interface McpUsageResponse {
13012
13099
  skipped: number;
13013
13100
  }
13014
13101
 
13102
+ // ── Apps data sources (DES-APPS-001 §5, §7.4, §7.5; api-types 0.175.0) ───────────────────────────
13103
+
13104
+ /** `McpServerConfigBody.sql`: a network SQL source's settings. Secrets go in `auth.ref` only. */
13105
+ export interface SqlSourceConfigBody {
13106
+ driver: 'postgres' | 'mysql';
13107
+ host: string;
13108
+ /** Default 5432 (Postgres), 3306 (MySQL). */
13109
+ port?: number;
13110
+ database: string;
13111
+ /** The login. A read-only login is recommended; the privilege report says when it is not one. */
13112
+ user: string;
13113
+ /**
13114
+ * `verify-full` (default; Postgres verify-full, MySQL VERIFY_IDENTITY: the certificate and the
13115
+ * host name are verified). `disable` only to loopback, or a private range confirmed as plaintext
13116
+ * in `address` (else the preview is a 409 `plaintext_refused`).
13117
+ */
13118
+ tls?: 'verify-full' | 'disable';
13119
+ /** A CA certificate (PEM) when the server's is not signed by a public root. */
13120
+ ca?: string;
13121
+ }
13122
+
13123
+ /** A `sql` source's settings as answered (the CA as whether one is set). */
13124
+ export interface SqlSourceView {
13125
+ driver: 'postgres' | 'mysql' | 'sqlite';
13126
+ host: string | null;
13127
+ port: number | null;
13128
+ database: string | null;
13129
+ user: string | null;
13130
+ tls: 'verify-full' | 'disable';
13131
+ ca: boolean;
13132
+ /** `sqlite`: the snapshot's sha256. */
13133
+ snapshot: string | null;
13134
+ }
13135
+
13136
+ /** How a relation may be read: base tables; views only by name (`viewsAllowed`); foreign tables never. */
13137
+ export type SourceRelationKind = 'table' | 'partitioned' | 'view' | 'matview' | 'foreign';
13138
+
13139
+ export interface SourceCatalogColumn {
13140
+ name: string;
13141
+ /** The source's own type text (`integer`, `character varying(80)`, `support.priority`). */
13142
+ type: string;
13143
+ nullable: boolean;
13144
+ /** Enum literals the schema declares (Postgres enum, MySQL ENUM). Never a value read from a row. */
13145
+ enumValues?: string[];
13146
+ }
13147
+
13148
+ export interface SourceCatalogRelation {
13149
+ /** Postgres schema, MySQL database; `null` for SQLite. */
13150
+ schema: string | null;
13151
+ name: string;
13152
+ kind: SourceRelationKind;
13153
+ /** The planner's estimate (SQLite: the snapshot's exact count); `null` = unknown. */
13154
+ rowEstimate: number | null;
13155
+ columns: SourceCatalogColumn[];
13156
+ primaryKey: string[];
13157
+ foreignKeys: Array<{ name: string; columns: string[]; references: { schema: string | null; table: string; columns: string[] } }>;
13158
+ /** Postgres: row security enabled or forced. */
13159
+ rowSecurity?: boolean;
13160
+ /** (api-types 0.176.0) Postgres: row security FORCED (it applies to the table's owner too). */
13161
+ rowSecurityForced?: boolean;
13162
+ }
13163
+
13164
+ /** A `sql` source's catalog: structure only. */
13165
+ export interface SqlSourceCatalog {
13166
+ dialect: 'postgres' | 'mysql' | 'sqlite';
13167
+ database: string | null;
13168
+ relations: SourceCatalogRelation[];
13169
+ describedAt: string;
13170
+ }
13171
+
13172
+ /** A `graphql` source's catalog: root fields and declared enums (from introspection). */
13173
+ export interface GraphqlSourceCatalog {
13174
+ queries: Array<{ name: string; type: string; args: Array<{ name: string; type: string }> }>;
13175
+ mutations: Array<{ name: string; type: string; args: Array<{ name: string; type: string }> }>;
13176
+ enums: Array<{ name: string; values: string[] }>;
13177
+ describedAt: string;
13178
+ }
13179
+
13180
+ export type SourceCatalog = SqlSourceCatalog | GraphqlSourceCatalog;
13181
+
13182
+ /** One declared Postgres row write, as the privilege report and the safety check take it (DES §7.4). */
13183
+ export interface SourceRowWrite {
13184
+ schema: string;
13185
+ table: string;
13186
+ op: 'insert' | 'update' | 'delete';
13187
+ /** The columns the write sets (an insert: every column of the table). */
13188
+ set: string[];
13189
+ /** Every primary-key column. */
13190
+ key: string[];
13191
+ }
13192
+
13193
+ /**
13194
+ * The Postgres privilege report (DES §5.1 "Test", §7.4 "the writer login"): what the login can read
13195
+ * and change, whether it is read-only, and per declared row write the EXACT `GRANT` statements still
13196
+ * missing: `USAGE` on the schema, table-level `SELECT` (the returned row type reads the whole row;
13197
+ * it covers the key and written columns), table-level `UPDATE` for every row write (the lock needs
13198
+ * it), and `INSERT` or `DELETE` for those operations.
13199
+ */
13200
+ export interface SourcePrivilegeReport {
13201
+ login: string;
13202
+ superuser: boolean;
13203
+ /**
13204
+ * Not a superuser, and no INSERT/UPDATE/DELETE/TRUNCATE (table or column level) on any visible
13205
+ * table, view (an updatable view writes its table) or foreign table, nor UPDATE or USAGE
13206
+ * (`nextval`) on a sequence.
13207
+ */
13208
+ readOnly: boolean;
13209
+ tables: Array<{ schema: string; table: string; select: boolean; selectSomeColumns: boolean; insert: boolean; update: boolean; delete: boolean }>;
13210
+ writes: Array<{ write: SourceRowWrite; missing: string[] }>;
13211
+ }
13212
+
13213
+ /** `GET /sources/:name/catalog`, `POST /sources/:name/describe` (re-describe now). */
13214
+ export interface SourceCatalogResponse {
13215
+ name: string;
13216
+ kind: 'sql' | 'graphql' | 'crew';
13217
+ catalog: SourceCatalog | CrewSourceCatalog;
13218
+ privileges?: SourcePrivilegeReport;
13219
+ descriptorHash: string | null;
13220
+ }
13221
+
13222
+ /** `POST /sources/:name/privileges`. */
13223
+ export interface SourcePrivilegesBody {
13224
+ writes?: SourceRowWrite[];
13225
+ }
13226
+
13227
+ /** `POST /sources/:name/check` — the per-kind source check: policy, then prepare/describe, never execute. */
13228
+ export interface SourceCheckBody {
13229
+ /** SQL text (Postgres `$1…`, MySQL and SQLite `?`), or a GraphQL document. */
13230
+ text: string;
13231
+ }
13232
+
13233
+ export type SourceCheckResponse =
13234
+ | { ok: true; columns: Array<{ name: string; type: string }>; params: string[]; relations: string[] }
13235
+ | {
13236
+ ok: false;
13237
+ /**
13238
+ * Why the query was refused. Two kinds of class:
13239
+ *
13240
+ * - The read policy, before anything reaches the source: `not_select`, `function`, `cast`,
13241
+ * `operator`, `relation`, `view`, `unqualified`, `qualified_name`, `column`, `recursive`,
13242
+ * `locking`, `into`, `statements`, `lexical`, `syntax` (NATURAL JOIN among them), `parse`,
13243
+ * `params`, `too_long`; GraphQL `operations`, `not_query`, `invalid`, `schema` (the described
13244
+ * schema does not validate: describe the source again).
13245
+ * - The source, after crew connected and asked it to prepare the text (never to execute it):
13246
+ * `prepare` (the source refused to prepare it; its own words reach a human only, an agent gets
13247
+ * the SQLSTATE), `authorizer` (SQLite's authorizer denied it), `refused` (a relation changed at
13248
+ * the source since the describe: describe it again), or a dialer refusal code.
13249
+ */
13250
+ code: string;
13251
+ detail: string;
13252
+ };
13253
+
13254
+ /** `POST /sources/:name/safety` — the Postgres table safety check (DES §7.4 rev 11). */
13255
+ export interface SourceSafetyBody {
13256
+ schema: string;
13257
+ table: string;
13258
+ /** A declared row write to check as well (key = the whole primary key; FK enforcement refused). */
13259
+ write?: { op: 'insert' | 'update' | 'delete'; set: string[]; key: string[] };
13260
+ }
13261
+
13262
+ export interface SourceSafetyResponse {
13263
+ table: { schema: string; name: string };
13264
+ safe: boolean;
13265
+ /**
13266
+ * Each reason a v1 row write may not touch the table, in words naming the object (`code`:
13267
+ * `not_a_table`, `partitioned`, `partition`, `access_method`, `inheritance_parent`,
13268
+ * `inheritance_child`, `row_security`, `rule`, `user_trigger`, `internal_trigger_disabled`,
13269
+ * `cascading_key`, `fk_operator`, `column_type`, `user_cast`, `generated_column`,
13270
+ * `exclusion_constraint`, `check_expression`, `check_dependency`, `index_expression`,
13271
+ * `index_partial`, `index_access_method`, `index_opclass`, `statistics_expression`, `depend_net`,
13272
+ * `no_primary_key`, `table_not_found`; for a declared write also `key_mismatch`, `key_write`,
13273
+ * `unknown_column`, `nothing_set`, `fk_enforcement`, `insert_columns`, `written_type`).
13274
+ */
13275
+ reasons: Array<{ code: string; detail: string }>;
13276
+ /** sha256 over the full definitions read; a grant binds to it (K2b). */
13277
+ fingerprint: string;
13278
+ }
13279
+
13280
+ /** `PUT /sources/:name/allow-writes` — human operator only (403 `writes_switch_human_only`). */
13281
+ export interface SourceAllowWritesBody {
13282
+ allowed: boolean;
13283
+ }
13284
+
13285
+ export interface SourceAllowWritesResponse {
13286
+ name: string;
13287
+ allowWrites: boolean;
13288
+ /** Row-write grants withdrawn by turning the switch off (0 when turning it on). */
13289
+ withdrawnGrants: number;
13290
+ }
13291
+
13292
+ /**
13293
+ * `POST /sources/:name/test-call` (G6) — human operator only. Without `confirm` it sends NOTHING and
13294
+ * answers the exact request it would send and its `requestHash`; with `confirm` equal to that hash it
13295
+ * sends exactly that one request. Reads only: a REST GET/HEAD operation, a GraphQL `query`, an MCP
13296
+ * tool whose class is `read`. Audited `apps.source.test_call`.
13297
+ */
13298
+ export interface SourceTestCallBody {
13299
+ /** REST: the tool (operation) name; MCP: the tool name; GraphQL: the query document. */
13300
+ target: string;
13301
+ args?: Record<string, unknown>;
13302
+ confirm?: string;
13303
+ }
13304
+
13305
+ export interface SourceTestCallRequest {
13306
+ kind: 'rest' | 'graphql' | 'mcp';
13307
+ /** REST/GraphQL: `GET https://api…/v1/tickets?page=1`; MCP: the tool name. */
13308
+ summary: string;
13309
+ method?: string;
13310
+ url?: string;
13311
+ /** Header NAMES only; the auth header's value is never shown. */
13312
+ headers?: string[];
13313
+ body?: unknown;
13314
+ tool?: string;
13315
+ args?: Record<string, unknown>;
13316
+ }
13317
+
13318
+ export type SourceTestCallResponse =
13319
+ | { sent: false; request: SourceTestCallRequest; requestHash: string }
13320
+ | { sent: true; request: SourceTestCallRequest; ok: boolean; status: number | null; result: unknown; truncated: boolean };
13321
+
13322
+ /** `POST /apps/uploads?name=<source>&filename=<file>` (body: the file's bytes) — a file becomes a `sql`/`sqlite` source. */
13323
+ export interface SourceUploadResponse {
13324
+ source: McpServer;
13325
+ snapshot: { digest: string; bytes: number; kind: 'csv' | 'xlsx' | 'sqlite' };
13326
+ /** The table a CSV/XLSX became; `null` for a `.sqlite` file. */
13327
+ table: string | null;
13328
+ /**
13329
+ * CSV/XLSX: whether the first row was taken as the header, and the column names. Only a HUMAN's
13330
+ * upload takes one (detected, or `header=yes`); a first row that looks like data, or holds values
13331
+ * such as an email, becomes `col_1…`, and an agent's upload always gets `col_1…` names.
13332
+ */
13333
+ header: { detected: boolean; columns: string[] } | null;
13334
+ /** The first 20 rows, answered to a HUMAN actor only (an agent gets `[]`). */
13335
+ sample: string[][];
13336
+ catalog: SqlSourceCatalog;
13337
+ }
13338
+
13339
+ /** The built-in `crew` source (DES §5.1): allowlisted GET routes, read in-process as the viewing actor. */
13340
+ export interface CrewSourceCatalog {
13341
+ routes: Array<{ path: string; responseType: string; params: string[] }>;
13342
+ }
13343
+
13015
13344
  // ── Decision capture (DES-decision-capture §4.2.1 / §4.6; DC-S4a, api-types 0.80.0) ──────────────
13016
13345
 
13017
13346
  /** The laya codebook's decision types. `none` is crew's label for "no decision". */
@@ -13834,7 +14163,18 @@ export interface DismissRecommendationResponse {
13834
14163
  export type McpInspectTarget =
13835
14164
  | { server: string }
13836
14165
  | { command: string; args?: string[]; env?: Record<string, string>; cwd?: string }
13837
- | { url: string; transport?: 'streamable-http' | 'sse'; headers?: Record<string, string> };
14166
+ | {
14167
+ url: string;
14168
+ transport?: 'streamable-http' | 'sse';
14169
+ headers?: Record<string, string>;
14170
+ /**
14171
+ * (api-types 0.174.0, DES-APPS-001 §5.2) Every request goes through crew's one dialer. A typed
14172
+ * loopback IP literal or `localhost` is reachable as typed (http allowed); a typed private IP
14173
+ * literal is reachable over https, and over http only with `plaintext: true` here; a private
14174
+ * host NAME needs a range here (a 400 for a range outside loopback/private).
14175
+ */
14176
+ address?: McpAddressPolicy;
14177
+ };
13838
14178
 
13839
14179
  /** `POST /mcp-inspect/sessions` */
13840
14180
  export interface McpInspectStartBody {
@@ -14738,6 +15078,38 @@ export interface AppLockAction {
14738
15078
  contractHash: string;
14739
15079
  }
14740
15080
 
15081
+ /**
15082
+ * (api-types 0.176.0, DES-APPS-001 K2b) One argument of a `.json` query text: a declared parameter of the
15083
+ * query, or a literal fixed by the app (a string of at most 1,000 characters). Viewer values are declared on
15084
+ * the query's parameters (`from`), never here.
15085
+ */
15086
+ export type AppQueryArg = { kind: 'param'; name: string } | { kind: 'literal'; value: string | number | boolean | null };
15087
+
15088
+ /**
15089
+ * (api-types 0.176.0) `queries/<id>.json` of a `rest` or `mcp` query: one registry tool the person accepted
15090
+ * as a read on the source sheet, and its arguments (at most 50, each one of the tool's input properties).
15091
+ */
15092
+ export interface AppToolQueryText {
15093
+ tool: string;
15094
+ args: Record<string, AppQueryArg>;
15095
+ }
15096
+
15097
+ /**
15098
+ * (api-types 0.176.0) `queries/<id>.json` of a `crew` query: one route the built-in crew source reads
15099
+ * (`SourceCatalogResponse` of `crew` lists them, e.g. `/runs/:id`), every `:param` of it in `params`, and
15100
+ * query-string values in `query`.
15101
+ */
15102
+ export interface AppCrewQueryText {
15103
+ route: string;
15104
+ params: Record<string, AppQueryArg>;
15105
+ query: Record<string, AppQueryArg>;
15106
+ }
15107
+
15108
+ // How a query's text binds its parameters (api-types 0.176.0): SQL `$n` (Postgres) and the n-th `?` (MySQL,
15109
+ // SQLite) bind the n-th parameter in the order `params.properties` declares them, and every declared
15110
+ // parameter is used; GraphQL variables are the parameters by name; `.json` texts name them in `AppQueryArg`s.
15111
+ // The order is part of the query's contract, so reordering the parameters is checked again.
15112
+
14741
15113
  // ── Apps: the store and its routes (DES §6.4, §7.6, §9.1) ────────────────────────────────────────
14742
15114
 
14743
15115
  /**
@@ -14945,7 +15317,13 @@ export interface AppQueryBody {
14945
15317
  /** One cell: values are rendered as text by the runtime. */
14946
15318
  export type AppCell = string | number | boolean | null;
14947
15319
 
14948
- /** `POST /apps/:app/query` 200 (DES §7.2). `rows` are aligned with `columns`. */
15320
+ /**
15321
+ * `POST /apps/:app/query` 200 (DES §7.2). `rows` are aligned with `columns`, which are exactly the query's
15322
+ * declared output (api-types 0.177.0: values coerced to their declared types; `integer` and `number` cells
15323
+ * are JS numbers within ±2^53; `date` is `YYYY-MM-DD`, `datetime` ISO 8601). `truncated`: a cap cut the
15324
+ * answer (5,000 rows, 10 MB, a cell past 64 KB cut). `hasMore`: the more path says another page exists.
15325
+ * `ms`: this request's time. Identical reads within the query's cache life share one answer.
15326
+ */
14949
15327
  export interface AppQueryResponse {
14950
15328
  columns: AppOutputColumn[];
14951
15329
  rows: AppCell[][];
@@ -14956,6 +15334,151 @@ export interface AppQueryResponse {
14956
15334
  cachedAt: number | null;
14957
15335
  }
14958
15336
 
15337
+ // ── Apps: the write path (api-types 0.178.0, DES-APPS-001 §7.3, §7.4, §9.4, slice K2b) ─────────────────
15338
+
15339
+ /** Where a value on an action card comes from (DES §7.3: "your sign-in", "fixed by the app", "filled by studio: now"). */
15340
+ export type AppActionValueSource = 'param' | 'app' | 'viewer' | 'crew';
15341
+
15342
+ /** One value on a card: the column or argument, the value as it will be sent, and where it comes from. */
15343
+ export interface AppActionCardValue {
15344
+ name: string;
15345
+ /** A list argument shows its items (an array parameter, the viewer's groups). */
15346
+ value: string | number | boolean | null | Array<string | number | boolean>;
15347
+ from: AppActionValueSource;
15348
+ /** The words for `from`: "you entered it", "fixed by the app", "your sign-in", "filled by studio: now". */
15349
+ label: string;
15350
+ }
15351
+
15352
+ /**
15353
+ * The card crew generates from the RESOLVED operation (DES §7.3) and the host draws outside the app's
15354
+ * frame: the only per-run consent. Every value is on it, literals included.
15355
+ */
15356
+ export type AppActionCard =
15357
+ | {
15358
+ kind: 'api';
15359
+ app: string;
15360
+ action: string;
15361
+ source: string;
15362
+ /** The source's kind: `rest`, `mcp-http`, `mcp-stdio` or `graphql`. */
15363
+ sourceKind: string;
15364
+ /** `POST /v1/tickets/4821/assign`, `mutation assign`, or `tool assign_ticket`. */
15365
+ operation: string;
15366
+ args: AppActionCardValue[];
15367
+ /** The request as it will be sent (method and URL and body, the GraphQL document and variables, or the tool call). */
15368
+ request: string;
15369
+ /** The action's description, labelled "The app says" by the host. */
15370
+ appSays?: string;
15371
+ }
15372
+ | {
15373
+ kind: 'row-write';
15374
+ app: string;
15375
+ action: string;
15376
+ source: string;
15377
+ /** The login the write runs as. */
15378
+ login: string;
15379
+ verb: 'INSERT' | 'UPDATE' | 'DELETE';
15380
+ /** Schema-qualified: `support.tickets`. */
15381
+ table: string;
15382
+ /** Every column it sets (an insert: every column of the table), with its value. */
15383
+ columns: AppActionCardValue[];
15384
+ /** The key (`id = 4821`). */
15385
+ key: AppActionCardValue[];
15386
+ /** "exactly 1 row, verified". */
15387
+ rows: string;
15388
+ /** "plain table: no triggers, rules, inheritance or row security; checked just now". */
15389
+ checks: string;
15390
+ /** The statement as it will run (values are its `$n` parameters, listed above). */
15391
+ statement: string;
15392
+ appSays?: string;
15393
+ };
15394
+
15395
+ /** `POST /apps/:app/actions/:id/prepare` (HUMAN operator). `params` are the action's declared, non-viewer parameters. */
15396
+ export interface AppActionPrepareBody {
15397
+ version: number | string;
15398
+ params?: Record<string, unknown>;
15399
+ }
15400
+
15401
+ /** `POST /apps/:app/actions/:id/prepare` 200: the record to run within 2 minutes, and its card. */
15402
+ export interface AppActionPrepareResponse {
15403
+ record: string;
15404
+ card: AppActionCard;
15405
+ /** Unix millis. */
15406
+ expiresAt: number;
15407
+ }
15408
+
15409
+ /** `POST /apps/:app/actions/:id/run` (HUMAN operator, the person who prepared it). */
15410
+ export interface AppActionRunBody {
15411
+ record: string;
15412
+ }
15413
+
15414
+ /**
15415
+ * An action record's states (DES §7.3): `prepared → running → succeeded | failed | unknown`. `running` is the
15416
+ * linearization point (persisted before the upstream call); `unknown` = the outcome could not be known (the
15417
+ * daemon restarted during the call, or the call was sent and no answer came). Nothing is ever re-run.
15418
+ */
15419
+ export type AppActionState = 'prepared' | 'running' | 'succeeded' | 'failed' | 'unknown';
15420
+
15421
+ /** `POST /apps/:app/actions/:id/run` 200: how it ended. */
15422
+ export interface AppActionRunResponse {
15423
+ record: string;
15424
+ state: 'succeeded' | 'failed' | 'unknown';
15425
+ /** Why it failed or is unknown, in crew's words. */
15426
+ reason?: string;
15427
+ /** A row write: `{ table, op, key }`; an API action: the answer, scrubbed and cut at 64 KB. */
15428
+ result?: unknown;
15429
+ }
15430
+
15431
+ /** `GET /apps/:app/actions/records/:id` 200 (the person who prepared it): answers a lost response. */
15432
+ export interface AppActionRecordView {
15433
+ id: string;
15434
+ app: string;
15435
+ action: string;
15436
+ version: number | null;
15437
+ tree: string;
15438
+ state: AppActionState;
15439
+ reason?: string;
15440
+ result?: unknown;
15441
+ card: AppActionCard;
15442
+ createdAt: number;
15443
+ expiresAt: number;
15444
+ endedAt?: number;
15445
+ }
15446
+
15447
+ /** `POST /apps/:app/actions/:id/grant` (HUMAN operator): grant the action as it is in this version. */
15448
+ export interface AppActionGrantBody {
15449
+ version: number | string;
15450
+ }
15451
+
15452
+ /**
15453
+ * A grant (DES §9.4): keyed by app and action, bound to the action hash, the contract hash (a row write's
15454
+ * holds the table's safety fingerprint) and the source descriptor; any change withdraws it. Turning a
15455
+ * source's Allow writes off withdraws its row-write grants.
15456
+ */
15457
+ export interface AppActionGrant {
15458
+ app: string;
15459
+ action: string;
15460
+ kind: 'api' | 'row-write';
15461
+ source: string;
15462
+ actionHash: string;
15463
+ contractHash: string;
15464
+ descriptorHash: string;
15465
+ /** A row write: the table safety check's fingerprint at grant. */
15466
+ fingerprint?: string;
15467
+ grantedBy: Actor;
15468
+ /** Unix millis. */
15469
+ grantedAt: number;
15470
+ }
15471
+
15472
+ /** `POST …/grant` 200 and `GET …/grant` 200 (observer). */
15473
+ export interface AppActionGrantResponse {
15474
+ grant: AppActionGrant;
15475
+ }
15476
+
15477
+ /** `DELETE …/grant` 200: whether a grant was there. */
15478
+ export interface AppActionRevokeResponse {
15479
+ revoked: boolean;
15480
+ }
15481
+
14959
15482
  /** One reason a check refused a tree. `path` is a JSON path into `apps.json`, or a repo path. */
14960
15483
  export interface AppCheckFinding {
14961
15484
  stage: 'spec' | 'files' | 'policy' | 'source';
@@ -14979,6 +15502,26 @@ export interface AppCheckFinding {
14979
15502
  * - 429 `rate_limited` (with `retryAfterMs`: a query queue or a per-viewer rate is full, DES §7.5);
14980
15503
  * - 501 `not_implemented` (a route a later slice serves; nothing happened);
14981
15504
  * - 503 `apps_unavailable`.
15505
+ *
15506
+ * (api-types 0.178.0, K2b) The action routes also answer: 409 `read_only` (`APPS_READ_ONLY` is set: no
15507
+ * write at all), `not_granted` (no grant for the action as it is now; a stale grant is withdrawn and says
15508
+ * so), `writes_off` (the source's Allow writes switch is off), `table_changed` (the row write's table no
15509
+ * longer passes the safety check, or its fingerprint differs from the grant's: the grant is withdrawn),
15510
+ * `value_does_not_fit` (a value its column would change, P28), `record_used` (the record already ran or is
15511
+ * running: nothing is re-run), `record_expired`, `missing_grants` (granting a row write whose login lacks a
15512
+ * privilege the write needs: the message lists the exact `GRANT` statements); 404 `unknown_action`,
15513
+ * `unknown_record`.
15514
+ *
15515
+ * (api-types 0.177.0, K2b) `POST /apps/:app/query` also answers: 400 `bad_params` (a parameter that is not
15516
+ * declared, does not satisfy its schema, is required and missing, or is viewer-bound and was sent); 403
15517
+ * `human_only` for an agent or plugin actor (an app's rows reach a person, never a model); 409
15518
+ * `viewer_unavailable` (a viewer-bound value crew does not know, e.g. no git `user.email` locally, or groups
15519
+ * in local preview), `contract_changed` (the source's connection, or what the query reads there, changed
15520
+ * since this version was checked: check it again), `query_refused` (the read policy or the source's live
15521
+ * relation checks refuse it now); 422 `result_invalid` (a value does not fit its declared column: the
15522
+ * message names the column and row, never the value); 502 `source_failed` / `source_unavailable` (the
15523
+ * source answered an error or could not be reached: a class and a SQLSTATE, never the source's words); 504
15524
+ * `source_timeout` (stopped at the 10 s deadline, at the source).
14982
15525
  */
14983
15526
  export interface AppErrorBody {
14984
15527
  code:
@@ -15004,7 +15547,25 @@ export interface AppErrorBody {
15004
15547
  | 'not_this_turn'
15005
15548
  | 'not_checked'
15006
15549
  | 'reviewer_not_distinct'
15007
- | 'apps_unavailable';
15550
+ | 'apps_unavailable'
15551
+ | 'bad_params'
15552
+ | 'viewer_unavailable'
15553
+ | 'contract_changed'
15554
+ | 'query_refused'
15555
+ | 'result_invalid'
15556
+ | 'source_failed'
15557
+ | 'source_unavailable'
15558
+ | 'source_timeout'
15559
+ | 'read_only'
15560
+ | 'not_granted'
15561
+ | 'writes_off'
15562
+ | 'table_changed'
15563
+ | 'value_does_not_fit'
15564
+ | 'record_used'
15565
+ | 'record_expired'
15566
+ | 'unknown_action'
15567
+ | 'unknown_record'
15568
+ | 'missing_grants';
15008
15569
  error: string;
15009
15570
  /** `rate_limited`: when to try again (also sent as `Retry-After`). */
15010
15571
  retryAfterMs?: number;
@@ -15042,9 +15603,15 @@ export type AppsCheckResponse =
15042
15603
  * serves that route for real rather than answering `501`.
15043
15604
  */
15044
15605
  export interface AppsCapabilities {
15045
- /** `POST /apps/:app/query` runs queries (until then it checks the receipt, then answers `501`). */
15606
+ /**
15607
+ * `POST /apps/:app/query` runs queries (until then it checks the receipt, then answers `501`). True since
15608
+ * api-types 0.177.0 (K2b, the executor).
15609
+ */
15046
15610
  query: boolean;
15047
- /** `POST /apps/:app/actions/:id/prepare|run|grant`, `GET …/actions/records/:id`. */
15611
+ /**
15612
+ * `POST /apps/:app/actions/:id/prepare|run|grant`, `GET|DELETE …/grant`, `GET …/actions/records/:id`. True
15613
+ * since api-types 0.178.0 (K2b, the write path: API actions and Postgres row writes).
15614
+ */
15048
15615
  actions: boolean;
15049
15616
  /** `POST /apps/:app/turns` launches `apps-turn` runs. */
15050
15617
  turns: boolean;
@@ -15052,7 +15619,10 @@ export interface AppsCapabilities {
15052
15619
  publish: boolean;
15053
15620
  /** `POST /apps/uploads`. */
15054
15621
  uploads: boolean;
15055
- /** The read policy and the per-kind source check run, so a change to queries or actions can land. */
15622
+ /**
15623
+ * The read policy and the per-kind source check run, so a change to queries or actions can land (true since
15624
+ * api-types 0.176.0 on a daemon with a connector registry: crew's source stage, DES §9.2 step 3).
15625
+ */
15056
15626
  sourceCheck: boolean;
15057
15627
  }
15058
15628
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-crew-api-types",
3
- "version": "0.173.0",
3
+ "version": "0.178.0",
4
4
  "description": "The wire contract of the wicked-crew daemon's /api/v1 REST surface and /ws CoreEvent frames \u2014 types only, zero runtime",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",