@1claw/openapi-spec 0.23.2 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,7 +40,7 @@ openapi-generator generate \
40
40
  import spec from "@1claw/openapi-spec/openapi.json";
41
41
  ```
42
42
 
43
- ## What's in the spec (v0.23.0 — API `info.version` 2.12.x)
43
+ ## What's in the spec (v0.23.2 — API `info.version` 2.13.0)
44
44
 
45
45
  - **OIDC Federation (1claw as IdP)** — `GET /.well-known/openid-configuration` (public discovery: issuer, jwks_uri, supported algs `["EdDSA","RS256"]`, supported grant types incl. token-exchange), `GET /.well-known/jwks.json` (public JWKS — every active EdDSA + RS256 key version, keyed by deterministic `kid`), `POST /v1/auth/federated-token` (RFC 8693 token exchange — accepts JSON or `application/x-www-form-urlencoded`; subject token is an agent JWT or `ocv_` API key; returns RS256 JWT scoped to `audience`). Agent fields: `federation_enabled`, `federation_audiences[]`, `federated_token_ttl_seconds`. Designed for Anthropic Workload Identity Federation, GCP STS, AWS STS, etc.
46
46
  - **Auth — agent JWT** — `POST /v1/auth/agent-token` documents optional JWT claim **`shroud_config`** when the agent has Shroud enabled (mirrors DB; consumed by Shroud PolicyEngine on LLM requests). Re-exchange after changing agent Shroud settings. Federation tokens use a separate KMS RSA-2048 key and are signed RS256.
@@ -59,7 +59,7 @@ import spec from "@1claw/openapi-spec/openapi.json";
59
59
  - **Audit** — Hash-chained event log
60
60
  - **Chains** — Supported blockchain registry
61
61
  - **Auth** — JWT, API keys, agent tokens, MFA, device flow, Google OAuth, **federated tokens (RFC 8693)**
62
- - **Platform** — Platform API for building multi-tenant apps on 1Claw: `POST/GET /v1/platform/apps`, `GET/PATCH/DELETE /v1/platform/apps/{id}`, `POST/GET /v1/platform/apps/{id}/templates`, `POST /v1/platform/users/upsert`, `POST /v1/platform/connections/{id}/bootstrap`, `GET /v1/platform/apps/{id}/users`, `GET /v1/platform/apps/{id}/audit`, `GET/DELETE /v1/platform/connected-apps`. Platform apps authenticate with `plt_` prefixed API keys. Supports OIDC user provisioning, bootstrap templates, and billing models (platform_pays, user_pays, hybrid).
62
+ - **Platform** — Platform API for building multi-tenant apps on 1Claw: `POST/GET /v1/platform/apps`, `GET/PATCH/DELETE /v1/platform/apps/{id}`, `POST/GET /v1/platform/apps/{id}/templates`, `POST /v1/platform/users/upsert`, `POST /v1/platform/connections/{id}/bootstrap`, `GET /v1/platform/apps/{id}/users`, `GET /v1/platform/apps/{id}/audit`, `GET/DELETE /v1/platform/connected-apps`, `GET /v1/platform/claim/{token}` (preview), `POST /v1/platform/claim/{token}` (redeem). Platform apps authenticate with `plt_` prefixed API keys. Supports OIDC user provisioning, bootstrap templates, and billing models (platform_pays, user_pays, hybrid).
63
63
  - **Org** — List members, invite, update/remove member; `GET /v1/org/agent-keys-vault` (users only, returns __agent-keys vault id or 404)
64
64
 
65
65
  ## Included files
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "1Claw API",
5
- "version": "2.12.0",
5
+ "version": "2.14.0",
6
6
  "description": "Secure secret management for AI agents. Provides vaults, secrets,\npolicy-based access control, agent identity, Intents API,\nsharing, billing, and audit logging.\n\nAll endpoints require JWT Bearer authentication unless marked with\n`security: []`.\n",
7
7
  "contact": {
8
8
  "email": "ops@1claw.xyz"
@@ -99,6 +99,10 @@
99
99
  "name": "Health",
100
100
  "description": "Service health checks"
101
101
  },
102
+ {
103
+ "name": "Approvals",
104
+ "description": "Human-in-the-loop approval workflow for agent actions"
105
+ },
102
106
  {
103
107
  "name": "Platform",
104
108
  "description": "Platform API for developers building on 1Claw (plt_ keys, user provisioning, bootstrap templates)"
@@ -1263,6 +1267,230 @@
1263
1267
  }
1264
1268
  }
1265
1269
  },
1270
+ "/v1/auth/devices": {
1271
+ "post": {
1272
+ "tags": [
1273
+ "Authentication"
1274
+ ],
1275
+ "summary": "Register a mobile device",
1276
+ "description": "Register a new mobile device for the authenticated user. Human-only.\nThe device public key is used for step-up authentication challenges.\n",
1277
+ "operationId": "registerDevice",
1278
+ "requestBody": {
1279
+ "required": true,
1280
+ "content": {
1281
+ "application/json": {
1282
+ "schema": {
1283
+ "$ref": "#/components/schemas/RegisterDeviceRequest"
1284
+ }
1285
+ }
1286
+ }
1287
+ },
1288
+ "responses": {
1289
+ "201": {
1290
+ "description": "Device registered",
1291
+ "content": {
1292
+ "application/json": {
1293
+ "schema": {
1294
+ "$ref": "#/components/schemas/RegisterDeviceResponse"
1295
+ }
1296
+ }
1297
+ }
1298
+ },
1299
+ "400": {
1300
+ "$ref": "#/components/responses/BadRequest"
1301
+ },
1302
+ "403": {
1303
+ "$ref": "#/components/responses/Forbidden"
1304
+ }
1305
+ }
1306
+ },
1307
+ "get": {
1308
+ "tags": [
1309
+ "Authentication"
1310
+ ],
1311
+ "summary": "List devices for current user",
1312
+ "description": "Returns all registered mobile devices for the authenticated user.",
1313
+ "operationId": "listDevices",
1314
+ "responses": {
1315
+ "200": {
1316
+ "description": "Device list",
1317
+ "content": {
1318
+ "application/json": {
1319
+ "schema": {
1320
+ "$ref": "#/components/schemas/DeviceListResponse"
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+ }
1326
+ }
1327
+ },
1328
+ "/v1/auth/devices/{device_id}": {
1329
+ "delete": {
1330
+ "tags": [
1331
+ "Authentication"
1332
+ ],
1333
+ "summary": "Revoke a device",
1334
+ "description": "Removes a registered device, invalidating its keys and push tokens.",
1335
+ "operationId": "revokeDevice",
1336
+ "parameters": [
1337
+ {
1338
+ "name": "device_id",
1339
+ "in": "path",
1340
+ "required": true,
1341
+ "schema": {
1342
+ "type": "string",
1343
+ "format": "uuid"
1344
+ }
1345
+ }
1346
+ ],
1347
+ "responses": {
1348
+ "204": {
1349
+ "description": "Device revoked"
1350
+ },
1351
+ "404": {
1352
+ "$ref": "#/components/responses/NotFound"
1353
+ }
1354
+ }
1355
+ }
1356
+ },
1357
+ "/v1/auth/devices/{device_id}/challenge": {
1358
+ "post": {
1359
+ "tags": [
1360
+ "Authentication"
1361
+ ],
1362
+ "summary": "Create step-up auth challenge",
1363
+ "description": "Creates a cryptographic challenge bound to a specific action (e.g. approving\na high-risk transaction). The device signs the challenge nonce to prove\npossession of the private key.\n",
1364
+ "operationId": "createDeviceChallenge",
1365
+ "parameters": [
1366
+ {
1367
+ "name": "device_id",
1368
+ "in": "path",
1369
+ "required": true,
1370
+ "schema": {
1371
+ "type": "string",
1372
+ "format": "uuid"
1373
+ }
1374
+ }
1375
+ ],
1376
+ "requestBody": {
1377
+ "required": true,
1378
+ "content": {
1379
+ "application/json": {
1380
+ "schema": {
1381
+ "$ref": "#/components/schemas/CreateDeviceChallengeRequest"
1382
+ }
1383
+ }
1384
+ }
1385
+ },
1386
+ "responses": {
1387
+ "200": {
1388
+ "description": "Challenge created",
1389
+ "content": {
1390
+ "application/json": {
1391
+ "schema": {
1392
+ "$ref": "#/components/schemas/DeviceChallengeResponse"
1393
+ }
1394
+ }
1395
+ }
1396
+ },
1397
+ "404": {
1398
+ "$ref": "#/components/responses/NotFound"
1399
+ }
1400
+ }
1401
+ }
1402
+ },
1403
+ "/v1/auth/devices/{device_id}/attest": {
1404
+ "post": {
1405
+ "tags": [
1406
+ "Authentication"
1407
+ ],
1408
+ "summary": "Attest device challenge",
1409
+ "description": "Submit a signed challenge nonce to complete step-up authentication.\nReturns a short-lived step-up token that can be used for the bound action.\n",
1410
+ "operationId": "attestDeviceChallenge",
1411
+ "parameters": [
1412
+ {
1413
+ "name": "device_id",
1414
+ "in": "path",
1415
+ "required": true,
1416
+ "schema": {
1417
+ "type": "string",
1418
+ "format": "uuid"
1419
+ }
1420
+ }
1421
+ ],
1422
+ "requestBody": {
1423
+ "required": true,
1424
+ "content": {
1425
+ "application/json": {
1426
+ "schema": {
1427
+ "$ref": "#/components/schemas/AttestDeviceChallengeRequest"
1428
+ }
1429
+ }
1430
+ }
1431
+ },
1432
+ "responses": {
1433
+ "200": {
1434
+ "description": "Attestation successful",
1435
+ "content": {
1436
+ "application/json": {
1437
+ "schema": {
1438
+ "$ref": "#/components/schemas/AttestDeviceChallengeResponse"
1439
+ }
1440
+ }
1441
+ }
1442
+ },
1443
+ "400": {
1444
+ "$ref": "#/components/responses/BadRequest"
1445
+ },
1446
+ "404": {
1447
+ "$ref": "#/components/responses/NotFound"
1448
+ }
1449
+ }
1450
+ }
1451
+ },
1452
+ "/v1/auth/devices/{device_id}/push-token": {
1453
+ "post": {
1454
+ "tags": [
1455
+ "Authentication"
1456
+ ],
1457
+ "summary": "Register push notification token",
1458
+ "description": "Associates a push notification token (APNs or FCM) with a registered device\nso the server can send approval requests and alerts.\n",
1459
+ "operationId": "registerPushToken",
1460
+ "parameters": [
1461
+ {
1462
+ "name": "device_id",
1463
+ "in": "path",
1464
+ "required": true,
1465
+ "schema": {
1466
+ "type": "string",
1467
+ "format": "uuid"
1468
+ }
1469
+ }
1470
+ ],
1471
+ "requestBody": {
1472
+ "required": true,
1473
+ "content": {
1474
+ "application/json": {
1475
+ "schema": {
1476
+ "$ref": "#/components/schemas/RegisterPushTokenRequest"
1477
+ }
1478
+ }
1479
+ }
1480
+ },
1481
+ "responses": {
1482
+ "204": {
1483
+ "description": "Push token registered"
1484
+ },
1485
+ "400": {
1486
+ "$ref": "#/components/responses/BadRequest"
1487
+ },
1488
+ "404": {
1489
+ "$ref": "#/components/responses/NotFound"
1490
+ }
1491
+ }
1492
+ }
1493
+ },
1266
1494
  "/v1/vaults": {
1267
1495
  "post": {
1268
1496
  "tags": [
@@ -5823,27 +6051,183 @@
5823
6051
  }
5824
6052
  }
5825
6053
  }
5826
- }
5827
- },
5828
- "components": {
5829
- "securitySchemes": {
5830
- "BearerAuth": {
5831
- "type": "http",
5832
- "scheme": "bearer",
5833
- "bearerFormat": "JWT"
5834
- },
5835
- "ApiKeyAuth": {
5836
- "type": "http",
5837
- "scheme": "bearer",
5838
- "description": "1ck_ prefixed API key used as Bearer token"
6054
+ },
6055
+ "/v1/approvals": {
6056
+ "get": {
6057
+ "tags": [
6058
+ "Approvals"
6059
+ ],
6060
+ "summary": "List pending approvals",
6061
+ "description": "Returns approvals for the authenticated user's organization.\nHuman-only. Supports filtering by status and pagination.\n",
6062
+ "operationId": "listApprovals",
6063
+ "parameters": [
6064
+ {
6065
+ "name": "status",
6066
+ "in": "query",
6067
+ "required": false,
6068
+ "schema": {
6069
+ "type": "string",
6070
+ "enum": [
6071
+ "pending",
6072
+ "approved",
6073
+ "rejected",
6074
+ "expired"
6075
+ ]
6076
+ },
6077
+ "description": "Filter by approval status"
6078
+ },
6079
+ {
6080
+ "name": "limit",
6081
+ "in": "query",
6082
+ "required": false,
6083
+ "schema": {
6084
+ "type": "integer",
6085
+ "default": 50
6086
+ }
6087
+ },
6088
+ {
6089
+ "name": "offset",
6090
+ "in": "query",
6091
+ "required": false,
6092
+ "schema": {
6093
+ "type": "integer",
6094
+ "default": 0
6095
+ }
6096
+ }
6097
+ ],
6098
+ "responses": {
6099
+ "200": {
6100
+ "description": "Approval list",
6101
+ "content": {
6102
+ "application/json": {
6103
+ "schema": {
6104
+ "type": "object",
6105
+ "required": [
6106
+ "approvals"
6107
+ ],
6108
+ "properties": {
6109
+ "approvals": {
6110
+ "type": "array",
6111
+ "items": {
6112
+ "$ref": "#/components/schemas/ApprovalResponse"
6113
+ }
6114
+ }
6115
+ }
6116
+ }
6117
+ }
6118
+ }
6119
+ }
6120
+ }
5839
6121
  }
5840
6122
  },
5841
- "parameters": {
5842
- "VaultId": {
5843
- "name": "vault_id",
5844
- "in": "path",
5845
- "required": true,
5846
- "schema": {
6123
+ "/v1/approvals/{approval_id}": {
6124
+ "get": {
6125
+ "tags": [
6126
+ "Approvals"
6127
+ ],
6128
+ "summary": "Get approval details",
6129
+ "description": "Returns details for a single approval by ID.",
6130
+ "operationId": "getApproval",
6131
+ "parameters": [
6132
+ {
6133
+ "name": "approval_id",
6134
+ "in": "path",
6135
+ "required": true,
6136
+ "schema": {
6137
+ "type": "string",
6138
+ "format": "uuid"
6139
+ }
6140
+ }
6141
+ ],
6142
+ "responses": {
6143
+ "200": {
6144
+ "description": "Approval details",
6145
+ "content": {
6146
+ "application/json": {
6147
+ "schema": {
6148
+ "$ref": "#/components/schemas/ApprovalResponse"
6149
+ }
6150
+ }
6151
+ }
6152
+ },
6153
+ "404": {
6154
+ "$ref": "#/components/responses/NotFound"
6155
+ }
6156
+ }
6157
+ }
6158
+ },
6159
+ "/v1/approvals/{approval_id}/decide": {
6160
+ "post": {
6161
+ "tags": [
6162
+ "Approvals"
6163
+ ],
6164
+ "summary": "Approve or reject",
6165
+ "description": "Submit a decision (approve or reject) for a pending approval.\nHuman-only. The approval must be in `pending` status.\n",
6166
+ "operationId": "decideApproval",
6167
+ "parameters": [
6168
+ {
6169
+ "name": "approval_id",
6170
+ "in": "path",
6171
+ "required": true,
6172
+ "schema": {
6173
+ "type": "string",
6174
+ "format": "uuid"
6175
+ }
6176
+ }
6177
+ ],
6178
+ "requestBody": {
6179
+ "required": true,
6180
+ "content": {
6181
+ "application/json": {
6182
+ "schema": {
6183
+ "$ref": "#/components/schemas/DecideApprovalRequest"
6184
+ }
6185
+ }
6186
+ }
6187
+ },
6188
+ "responses": {
6189
+ "200": {
6190
+ "description": "Decision recorded",
6191
+ "content": {
6192
+ "application/json": {
6193
+ "schema": {
6194
+ "$ref": "#/components/schemas/ApprovalResponse"
6195
+ }
6196
+ }
6197
+ }
6198
+ },
6199
+ "400": {
6200
+ "$ref": "#/components/responses/BadRequest"
6201
+ },
6202
+ "404": {
6203
+ "$ref": "#/components/responses/NotFound"
6204
+ },
6205
+ "409": {
6206
+ "$ref": "#/components/responses/Conflict"
6207
+ }
6208
+ }
6209
+ }
6210
+ }
6211
+ },
6212
+ "components": {
6213
+ "securitySchemes": {
6214
+ "BearerAuth": {
6215
+ "type": "http",
6216
+ "scheme": "bearer",
6217
+ "bearerFormat": "JWT"
6218
+ },
6219
+ "ApiKeyAuth": {
6220
+ "type": "http",
6221
+ "scheme": "bearer",
6222
+ "description": "1ck_ prefixed API key used as Bearer token"
6223
+ }
6224
+ },
6225
+ "parameters": {
6226
+ "VaultId": {
6227
+ "name": "vault_id",
6228
+ "in": "path",
6229
+ "required": true,
6230
+ "schema": {
5847
6231
  "type": "string",
5848
6232
  "format": "uuid"
5849
6233
  }
@@ -10734,6 +11118,39 @@
10734
11118
  "type": "string",
10735
11119
  "format": "uuid"
10736
11120
  }
11121
+ },
11122
+ "signing_key_chains": {
11123
+ "type": "array",
11124
+ "items": {
11125
+ "type": "string"
11126
+ },
11127
+ "description": "Chains with provisioned signing keys"
11128
+ },
11129
+ "agent_api_key": {
11130
+ "type": "string",
11131
+ "nullable": true,
11132
+ "description": "One-time agent API key (ocv_ prefix). Store securely — not retrievable later."
11133
+ },
11134
+ "signing_keys": {
11135
+ "type": "array",
11136
+ "description": "Provisioned signing key details (chain, address, public key)",
11137
+ "items": {
11138
+ "type": "object",
11139
+ "properties": {
11140
+ "chain": {
11141
+ "type": "string"
11142
+ },
11143
+ "curve": {
11144
+ "type": "string"
11145
+ },
11146
+ "public_key": {
11147
+ "type": "string"
11148
+ },
11149
+ "address": {
11150
+ "type": "string"
11151
+ }
11152
+ }
11153
+ }
10737
11154
  }
10738
11155
  }
10739
11156
  }
@@ -10855,6 +11272,298 @@
10855
11272
  "type": "string"
10856
11273
  }
10857
11274
  }
11275
+ },
11276
+ "RegisterDeviceRequest": {
11277
+ "type": "object",
11278
+ "required": [
11279
+ "name",
11280
+ "platform",
11281
+ "public_key_pem"
11282
+ ],
11283
+ "properties": {
11284
+ "name": {
11285
+ "type": "string",
11286
+ "description": "Human-readable device name (e.g. \"Kevin's iPhone\")",
11287
+ "example": "My iPhone"
11288
+ },
11289
+ "platform": {
11290
+ "type": "string",
11291
+ "enum": [
11292
+ "ios",
11293
+ "android"
11294
+ ]
11295
+ },
11296
+ "public_key_pem": {
11297
+ "type": "string",
11298
+ "description": "PEM-encoded public key for step-up challenge signing"
11299
+ },
11300
+ "attestation_blob": {
11301
+ "type": "string",
11302
+ "description": "Optional platform attestation (Apple DeviceCheck / Android SafetyNet)"
11303
+ }
11304
+ }
11305
+ },
11306
+ "RegisterDeviceResponse": {
11307
+ "type": "object",
11308
+ "required": [
11309
+ "device_id",
11310
+ "attestation_verified"
11311
+ ],
11312
+ "properties": {
11313
+ "device_id": {
11314
+ "type": "string",
11315
+ "format": "uuid"
11316
+ },
11317
+ "attestation_verified": {
11318
+ "type": "boolean"
11319
+ }
11320
+ }
11321
+ },
11322
+ "DeviceListResponse": {
11323
+ "type": "object",
11324
+ "required": [
11325
+ "devices"
11326
+ ],
11327
+ "properties": {
11328
+ "devices": {
11329
+ "type": "array",
11330
+ "items": {
11331
+ "$ref": "#/components/schemas/DeviceResponse"
11332
+ }
11333
+ }
11334
+ }
11335
+ },
11336
+ "DeviceResponse": {
11337
+ "type": "object",
11338
+ "required": [
11339
+ "id",
11340
+ "name",
11341
+ "platform",
11342
+ "attestation_verified",
11343
+ "created_at"
11344
+ ],
11345
+ "properties": {
11346
+ "id": {
11347
+ "type": "string",
11348
+ "format": "uuid"
11349
+ },
11350
+ "name": {
11351
+ "type": "string"
11352
+ },
11353
+ "platform": {
11354
+ "type": "string"
11355
+ },
11356
+ "attestation_verified": {
11357
+ "type": "boolean"
11358
+ },
11359
+ "last_used_at": {
11360
+ "type": "string",
11361
+ "format": "date-time",
11362
+ "nullable": true
11363
+ },
11364
+ "created_at": {
11365
+ "type": "string",
11366
+ "format": "date-time"
11367
+ }
11368
+ }
11369
+ },
11370
+ "CreateDeviceChallengeRequest": {
11371
+ "type": "object",
11372
+ "required": [
11373
+ "action",
11374
+ "target_id"
11375
+ ],
11376
+ "properties": {
11377
+ "action": {
11378
+ "type": "string",
11379
+ "description": "The action this challenge authorizes (e.g. \"approve_transaction\")"
11380
+ },
11381
+ "target_id": {
11382
+ "type": "string",
11383
+ "description": "ID of the resource the action targets"
11384
+ }
11385
+ }
11386
+ },
11387
+ "DeviceChallengeResponse": {
11388
+ "type": "object",
11389
+ "required": [
11390
+ "challenge_nonce",
11391
+ "expires_at",
11392
+ "action_bound_hash"
11393
+ ],
11394
+ "properties": {
11395
+ "challenge_nonce": {
11396
+ "type": "string"
11397
+ },
11398
+ "expires_at": {
11399
+ "type": "string",
11400
+ "format": "date-time"
11401
+ },
11402
+ "action_bound_hash": {
11403
+ "type": "string",
11404
+ "description": "SHA-256 binding the challenge to the requested action and target"
11405
+ }
11406
+ }
11407
+ },
11408
+ "AttestDeviceChallengeRequest": {
11409
+ "type": "object",
11410
+ "required": [
11411
+ "challenge_nonce",
11412
+ "signature"
11413
+ ],
11414
+ "properties": {
11415
+ "challenge_nonce": {
11416
+ "type": "string"
11417
+ },
11418
+ "signature": {
11419
+ "type": "string",
11420
+ "description": "Signature over the challenge nonce using the device's private key"
11421
+ }
11422
+ }
11423
+ },
11424
+ "AttestDeviceChallengeResponse": {
11425
+ "type": "object",
11426
+ "required": [
11427
+ "step_up_token",
11428
+ "expires_at"
11429
+ ],
11430
+ "properties": {
11431
+ "step_up_token": {
11432
+ "type": "string",
11433
+ "description": "Short-lived token authorizing the bound action"
11434
+ },
11435
+ "expires_at": {
11436
+ "type": "string",
11437
+ "format": "date-time"
11438
+ }
11439
+ }
11440
+ },
11441
+ "RegisterPushTokenRequest": {
11442
+ "type": "object",
11443
+ "required": [
11444
+ "token",
11445
+ "platform"
11446
+ ],
11447
+ "properties": {
11448
+ "token": {
11449
+ "type": "string",
11450
+ "description": "Push notification token from APNs or FCM"
11451
+ },
11452
+ "platform": {
11453
+ "type": "string",
11454
+ "enum": [
11455
+ "apns",
11456
+ "fcm"
11457
+ ]
11458
+ }
11459
+ }
11460
+ },
11461
+ "DecideApprovalRequest": {
11462
+ "type": "object",
11463
+ "required": [
11464
+ "decision"
11465
+ ],
11466
+ "properties": {
11467
+ "decision": {
11468
+ "type": "string",
11469
+ "enum": [
11470
+ "approve",
11471
+ "reject"
11472
+ ]
11473
+ },
11474
+ "reason": {
11475
+ "type": "string",
11476
+ "description": "Optional human-readable reason for the decision"
11477
+ }
11478
+ }
11479
+ },
11480
+ "ApprovalResponse": {
11481
+ "type": "object",
11482
+ "required": [
11483
+ "id",
11484
+ "org_id",
11485
+ "user_id",
11486
+ "action",
11487
+ "target_type",
11488
+ "target_id",
11489
+ "risk_tier",
11490
+ "status",
11491
+ "summary",
11492
+ "created_at"
11493
+ ],
11494
+ "properties": {
11495
+ "id": {
11496
+ "type": "string",
11497
+ "format": "uuid"
11498
+ },
11499
+ "org_id": {
11500
+ "type": "string",
11501
+ "format": "uuid"
11502
+ },
11503
+ "user_id": {
11504
+ "type": "string",
11505
+ "format": "uuid"
11506
+ },
11507
+ "agent_id": {
11508
+ "type": "string",
11509
+ "format": "uuid",
11510
+ "nullable": true
11511
+ },
11512
+ "action": {
11513
+ "type": "string"
11514
+ },
11515
+ "target_type": {
11516
+ "type": "string"
11517
+ },
11518
+ "target_id": {
11519
+ "type": "string"
11520
+ },
11521
+ "risk_tier": {
11522
+ "type": "integer",
11523
+ "minimum": 1,
11524
+ "maximum": 3
11525
+ },
11526
+ "status": {
11527
+ "type": "string",
11528
+ "enum": [
11529
+ "pending",
11530
+ "approved",
11531
+ "rejected",
11532
+ "expired"
11533
+ ]
11534
+ },
11535
+ "summary": {
11536
+ "type": "object",
11537
+ "description": "Structured summary of the action requiring approval"
11538
+ },
11539
+ "reason": {
11540
+ "type": "string",
11541
+ "nullable": true
11542
+ },
11543
+ "decision_reason": {
11544
+ "type": "string",
11545
+ "nullable": true
11546
+ },
11547
+ "decided_by": {
11548
+ "type": "string",
11549
+ "format": "uuid",
11550
+ "nullable": true
11551
+ },
11552
+ "decided_at": {
11553
+ "type": "string",
11554
+ "format": "date-time",
11555
+ "nullable": true
11556
+ },
11557
+ "expires_at": {
11558
+ "type": "string",
11559
+ "format": "date-time",
11560
+ "nullable": true
11561
+ },
11562
+ "created_at": {
11563
+ "type": "string",
11564
+ "format": "date-time"
11565
+ }
11566
+ }
10858
11567
  }
10859
11568
  }
10860
11569
  }
package/openapi.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.1.0
2
2
 
3
3
  info:
4
4
  title: 1Claw API
5
- version: 2.12.0
5
+ version: 2.14.0
6
6
  description: |
7
7
  Secure secret management for AI agents. Provides vaults, secrets,
8
8
  policy-based access control, agent identity, Intents API,
@@ -62,6 +62,8 @@ tags:
62
62
  description: Platform administration
63
63
  - name: Health
64
64
  description: Service health checks
65
+ - name: Approvals
66
+ description: Human-in-the-loop approval workflow for agent actions
65
67
  - name: Platform
66
68
  description: Platform API for developers building on 1Claw (plt_ keys, user provisioning, bootstrap templates)
67
69
 
@@ -871,6 +873,157 @@ paths:
871
873
  "403":
872
874
  $ref: "#/components/responses/Forbidden"
873
875
 
876
+ /v1/auth/devices:
877
+ post:
878
+ tags: [Authentication]
879
+ summary: Register a mobile device
880
+ description: |
881
+ Register a new mobile device for the authenticated user. Human-only.
882
+ The device public key is used for step-up authentication challenges.
883
+ operationId: registerDevice
884
+ requestBody:
885
+ required: true
886
+ content:
887
+ application/json:
888
+ schema:
889
+ $ref: "#/components/schemas/RegisterDeviceRequest"
890
+ responses:
891
+ "201":
892
+ description: Device registered
893
+ content:
894
+ application/json:
895
+ schema:
896
+ $ref: "#/components/schemas/RegisterDeviceResponse"
897
+ "400":
898
+ $ref: "#/components/responses/BadRequest"
899
+ "403":
900
+ $ref: "#/components/responses/Forbidden"
901
+ get:
902
+ tags: [Authentication]
903
+ summary: List devices for current user
904
+ description: Returns all registered mobile devices for the authenticated user.
905
+ operationId: listDevices
906
+ responses:
907
+ "200":
908
+ description: Device list
909
+ content:
910
+ application/json:
911
+ schema:
912
+ $ref: "#/components/schemas/DeviceListResponse"
913
+
914
+ /v1/auth/devices/{device_id}:
915
+ delete:
916
+ tags: [Authentication]
917
+ summary: Revoke a device
918
+ description: Removes a registered device, invalidating its keys and push tokens.
919
+ operationId: revokeDevice
920
+ parameters:
921
+ - name: device_id
922
+ in: path
923
+ required: true
924
+ schema:
925
+ type: string
926
+ format: uuid
927
+ responses:
928
+ "204":
929
+ description: Device revoked
930
+ "404":
931
+ $ref: "#/components/responses/NotFound"
932
+
933
+ /v1/auth/devices/{device_id}/challenge:
934
+ post:
935
+ tags: [Authentication]
936
+ summary: Create step-up auth challenge
937
+ description: |
938
+ Creates a cryptographic challenge bound to a specific action (e.g. approving
939
+ a high-risk transaction). The device signs the challenge nonce to prove
940
+ possession of the private key.
941
+ operationId: createDeviceChallenge
942
+ parameters:
943
+ - name: device_id
944
+ in: path
945
+ required: true
946
+ schema:
947
+ type: string
948
+ format: uuid
949
+ requestBody:
950
+ required: true
951
+ content:
952
+ application/json:
953
+ schema:
954
+ $ref: "#/components/schemas/CreateDeviceChallengeRequest"
955
+ responses:
956
+ "200":
957
+ description: Challenge created
958
+ content:
959
+ application/json:
960
+ schema:
961
+ $ref: "#/components/schemas/DeviceChallengeResponse"
962
+ "404":
963
+ $ref: "#/components/responses/NotFound"
964
+
965
+ /v1/auth/devices/{device_id}/attest:
966
+ post:
967
+ tags: [Authentication]
968
+ summary: Attest device challenge
969
+ description: |
970
+ Submit a signed challenge nonce to complete step-up authentication.
971
+ Returns a short-lived step-up token that can be used for the bound action.
972
+ operationId: attestDeviceChallenge
973
+ parameters:
974
+ - name: device_id
975
+ in: path
976
+ required: true
977
+ schema:
978
+ type: string
979
+ format: uuid
980
+ requestBody:
981
+ required: true
982
+ content:
983
+ application/json:
984
+ schema:
985
+ $ref: "#/components/schemas/AttestDeviceChallengeRequest"
986
+ responses:
987
+ "200":
988
+ description: Attestation successful
989
+ content:
990
+ application/json:
991
+ schema:
992
+ $ref: "#/components/schemas/AttestDeviceChallengeResponse"
993
+ "400":
994
+ $ref: "#/components/responses/BadRequest"
995
+ "404":
996
+ $ref: "#/components/responses/NotFound"
997
+
998
+ /v1/auth/devices/{device_id}/push-token:
999
+ post:
1000
+ tags: [Authentication]
1001
+ summary: Register push notification token
1002
+ description: |
1003
+ Associates a push notification token (APNs or FCM) with a registered device
1004
+ so the server can send approval requests and alerts.
1005
+ operationId: registerPushToken
1006
+ parameters:
1007
+ - name: device_id
1008
+ in: path
1009
+ required: true
1010
+ schema:
1011
+ type: string
1012
+ format: uuid
1013
+ requestBody:
1014
+ required: true
1015
+ content:
1016
+ application/json:
1017
+ schema:
1018
+ $ref: "#/components/schemas/RegisterPushTokenRequest"
1019
+ responses:
1020
+ "204":
1021
+ description: Push token registered
1022
+ "400":
1023
+ $ref: "#/components/responses/BadRequest"
1024
+ "404":
1025
+ $ref: "#/components/responses/NotFound"
1026
+
874
1027
  # ---------------------------------------------------------------------------
875
1028
  # Vaults
876
1029
  # ---------------------------------------------------------------------------
@@ -3780,6 +3933,108 @@ paths:
3780
3933
  "410":
3781
3934
  description: Claim token has expired
3782
3935
 
3936
+ # --- Approvals ---
3937
+
3938
+ /v1/approvals:
3939
+ get:
3940
+ tags: [Approvals]
3941
+ summary: List pending approvals
3942
+ description: |
3943
+ Returns approvals for the authenticated user's organization.
3944
+ Human-only. Supports filtering by status and pagination.
3945
+ operationId: listApprovals
3946
+ parameters:
3947
+ - name: status
3948
+ in: query
3949
+ required: false
3950
+ schema:
3951
+ type: string
3952
+ enum: [pending, approved, rejected, expired]
3953
+ description: Filter by approval status
3954
+ - name: limit
3955
+ in: query
3956
+ required: false
3957
+ schema:
3958
+ type: integer
3959
+ default: 50
3960
+ - name: offset
3961
+ in: query
3962
+ required: false
3963
+ schema:
3964
+ type: integer
3965
+ default: 0
3966
+ responses:
3967
+ "200":
3968
+ description: Approval list
3969
+ content:
3970
+ application/json:
3971
+ schema:
3972
+ type: object
3973
+ required: [approvals]
3974
+ properties:
3975
+ approvals:
3976
+ type: array
3977
+ items:
3978
+ $ref: "#/components/schemas/ApprovalResponse"
3979
+
3980
+ /v1/approvals/{approval_id}:
3981
+ get:
3982
+ tags: [Approvals]
3983
+ summary: Get approval details
3984
+ description: Returns details for a single approval by ID.
3985
+ operationId: getApproval
3986
+ parameters:
3987
+ - name: approval_id
3988
+ in: path
3989
+ required: true
3990
+ schema:
3991
+ type: string
3992
+ format: uuid
3993
+ responses:
3994
+ "200":
3995
+ description: Approval details
3996
+ content:
3997
+ application/json:
3998
+ schema:
3999
+ $ref: "#/components/schemas/ApprovalResponse"
4000
+ "404":
4001
+ $ref: "#/components/responses/NotFound"
4002
+
4003
+ /v1/approvals/{approval_id}/decide:
4004
+ post:
4005
+ tags: [Approvals]
4006
+ summary: Approve or reject
4007
+ description: |
4008
+ Submit a decision (approve or reject) for a pending approval.
4009
+ Human-only. The approval must be in `pending` status.
4010
+ operationId: decideApproval
4011
+ parameters:
4012
+ - name: approval_id
4013
+ in: path
4014
+ required: true
4015
+ schema:
4016
+ type: string
4017
+ format: uuid
4018
+ requestBody:
4019
+ required: true
4020
+ content:
4021
+ application/json:
4022
+ schema:
4023
+ $ref: "#/components/schemas/DecideApprovalRequest"
4024
+ responses:
4025
+ "200":
4026
+ description: Decision recorded
4027
+ content:
4028
+ application/json:
4029
+ schema:
4030
+ $ref: "#/components/schemas/ApprovalResponse"
4031
+ "400":
4032
+ $ref: "#/components/responses/BadRequest"
4033
+ "404":
4034
+ $ref: "#/components/responses/NotFound"
4035
+ "409":
4036
+ $ref: "#/components/responses/Conflict"
4037
+
3783
4038
  # =============================================================================
3784
4039
  # COMPONENTS
3785
4040
  # =============================================================================
@@ -7222,6 +7477,29 @@ components:
7222
7477
  items:
7223
7478
  type: string
7224
7479
  format: uuid
7480
+ signing_key_chains:
7481
+ type: array
7482
+ items:
7483
+ type: string
7484
+ description: Chains with provisioned signing keys
7485
+ agent_api_key:
7486
+ type: string
7487
+ nullable: true
7488
+ description: One-time agent API key (ocv_ prefix). Store securely — not retrievable later.
7489
+ signing_keys:
7490
+ type: array
7491
+ description: Provisioned signing key details (chain, address, public key)
7492
+ items:
7493
+ type: object
7494
+ properties:
7495
+ chain:
7496
+ type: string
7497
+ curve:
7498
+ type: string
7499
+ public_key:
7500
+ type: string
7501
+ address:
7502
+ type: string
7225
7503
 
7226
7504
  ConnectedAppResponse:
7227
7505
  type: object
@@ -7306,3 +7584,185 @@ components:
7306
7584
  nullable: true
7307
7585
  dashboard_url:
7308
7586
  type: string
7587
+
7588
+ # --- Mobile Companion App schemas ---
7589
+
7590
+ RegisterDeviceRequest:
7591
+ type: object
7592
+ required: [name, platform, public_key_pem]
7593
+ properties:
7594
+ name:
7595
+ type: string
7596
+ description: Human-readable device name (e.g. "Kevin's iPhone")
7597
+ example: My iPhone
7598
+ platform:
7599
+ type: string
7600
+ enum: [ios, android]
7601
+ public_key_pem:
7602
+ type: string
7603
+ description: PEM-encoded public key for step-up challenge signing
7604
+ attestation_blob:
7605
+ type: string
7606
+ description: Optional platform attestation (Apple DeviceCheck / Android SafetyNet)
7607
+
7608
+ RegisterDeviceResponse:
7609
+ type: object
7610
+ required: [device_id, attestation_verified]
7611
+ properties:
7612
+ device_id:
7613
+ type: string
7614
+ format: uuid
7615
+ attestation_verified:
7616
+ type: boolean
7617
+
7618
+ DeviceListResponse:
7619
+ type: object
7620
+ required: [devices]
7621
+ properties:
7622
+ devices:
7623
+ type: array
7624
+ items:
7625
+ $ref: "#/components/schemas/DeviceResponse"
7626
+
7627
+ DeviceResponse:
7628
+ type: object
7629
+ required: [id, name, platform, attestation_verified, created_at]
7630
+ properties:
7631
+ id:
7632
+ type: string
7633
+ format: uuid
7634
+ name:
7635
+ type: string
7636
+ platform:
7637
+ type: string
7638
+ attestation_verified:
7639
+ type: boolean
7640
+ last_used_at:
7641
+ type: string
7642
+ format: date-time
7643
+ nullable: true
7644
+ created_at:
7645
+ type: string
7646
+ format: date-time
7647
+
7648
+ CreateDeviceChallengeRequest:
7649
+ type: object
7650
+ required: [action, target_id]
7651
+ properties:
7652
+ action:
7653
+ type: string
7654
+ description: The action this challenge authorizes (e.g. "approve_transaction")
7655
+ target_id:
7656
+ type: string
7657
+ description: ID of the resource the action targets
7658
+
7659
+ DeviceChallengeResponse:
7660
+ type: object
7661
+ required: [challenge_nonce, expires_at, action_bound_hash]
7662
+ properties:
7663
+ challenge_nonce:
7664
+ type: string
7665
+ expires_at:
7666
+ type: string
7667
+ format: date-time
7668
+ action_bound_hash:
7669
+ type: string
7670
+ description: SHA-256 binding the challenge to the requested action and target
7671
+
7672
+ AttestDeviceChallengeRequest:
7673
+ type: object
7674
+ required: [challenge_nonce, signature]
7675
+ properties:
7676
+ challenge_nonce:
7677
+ type: string
7678
+ signature:
7679
+ type: string
7680
+ description: Signature over the challenge nonce using the device's private key
7681
+
7682
+ AttestDeviceChallengeResponse:
7683
+ type: object
7684
+ required: [step_up_token, expires_at]
7685
+ properties:
7686
+ step_up_token:
7687
+ type: string
7688
+ description: Short-lived token authorizing the bound action
7689
+ expires_at:
7690
+ type: string
7691
+ format: date-time
7692
+
7693
+ RegisterPushTokenRequest:
7694
+ type: object
7695
+ required: [token, platform]
7696
+ properties:
7697
+ token:
7698
+ type: string
7699
+ description: Push notification token from APNs or FCM
7700
+ platform:
7701
+ type: string
7702
+ enum: [apns, fcm]
7703
+
7704
+ DecideApprovalRequest:
7705
+ type: object
7706
+ required: [decision]
7707
+ properties:
7708
+ decision:
7709
+ type: string
7710
+ enum: [approve, reject]
7711
+ reason:
7712
+ type: string
7713
+ description: Optional human-readable reason for the decision
7714
+
7715
+ ApprovalResponse:
7716
+ type: object
7717
+ required: [id, org_id, user_id, action, target_type, target_id, risk_tier, status, summary, created_at]
7718
+ properties:
7719
+ id:
7720
+ type: string
7721
+ format: uuid
7722
+ org_id:
7723
+ type: string
7724
+ format: uuid
7725
+ user_id:
7726
+ type: string
7727
+ format: uuid
7728
+ agent_id:
7729
+ type: string
7730
+ format: uuid
7731
+ nullable: true
7732
+ action:
7733
+ type: string
7734
+ target_type:
7735
+ type: string
7736
+ target_id:
7737
+ type: string
7738
+ risk_tier:
7739
+ type: integer
7740
+ minimum: 1
7741
+ maximum: 3
7742
+ status:
7743
+ type: string
7744
+ enum: [pending, approved, rejected, expired]
7745
+ summary:
7746
+ type: object
7747
+ description: Structured summary of the action requiring approval
7748
+ reason:
7749
+ type: string
7750
+ nullable: true
7751
+ decision_reason:
7752
+ type: string
7753
+ nullable: true
7754
+ decided_by:
7755
+ type: string
7756
+ format: uuid
7757
+ nullable: true
7758
+ decided_at:
7759
+ type: string
7760
+ format: date-time
7761
+ nullable: true
7762
+ expires_at:
7763
+ type: string
7764
+ format: date-time
7765
+ nullable: true
7766
+ created_at:
7767
+ type: string
7768
+ format: date-time
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1claw/openapi-spec",
3
- "version": "0.23.2",
3
+ "version": "0.24.0",
4
4
  "description": "OpenAPI 3.1.0 specification for the 1Claw Vault API — generate clients in any language",
5
5
  "license": "MIT",
6
6
  "repository": {