@1claw/openapi-spec 0.23.1 → 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/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": [
@@ -5749,56 +5977,286 @@
5749
5977
  }
5750
5978
  }
5751
5979
  }
5752
- }
5753
- },
5754
- "components": {
5755
- "securitySchemes": {
5756
- "BearerAuth": {
5757
- "type": "http",
5758
- "scheme": "bearer",
5759
- "bearerFormat": "JWT"
5760
- },
5761
- "ApiKeyAuth": {
5762
- "type": "http",
5763
- "scheme": "bearer",
5764
- "description": "1ck_ prefixed API key used as Bearer token"
5765
- }
5766
5980
  },
5767
- "parameters": {
5768
- "VaultId": {
5769
- "name": "vault_id",
5770
- "in": "path",
5771
- "required": true,
5772
- "schema": {
5773
- "type": "string",
5774
- "format": "uuid"
5775
- }
5776
- },
5777
- "SecretPath": {
5778
- "name": "path",
5779
- "in": "path",
5780
- "required": true,
5781
- "schema": {
5782
- "type": "string"
5783
- },
5784
- "description": "Secret path (e.g. \"db/credentials\")"
5785
- },
5786
- "AgentId": {
5787
- "name": "agent_id",
5788
- "in": "path",
5789
- "required": true,
5790
- "schema": {
5791
- "type": "string",
5792
- "format": "uuid"
5981
+ "/v1/platform/claim/{token}": {
5982
+ "get": {
5983
+ "tags": [
5984
+ "Platform"
5985
+ ],
5986
+ "summary": "Preview a claim token",
5987
+ "description": "Verify a claim token and preview what was provisioned (app name, vaults, agents, policies).\nPublic endpoint — the token itself is the authentication.\n",
5988
+ "parameters": [
5989
+ {
5990
+ "in": "path",
5991
+ "name": "token",
5992
+ "required": true,
5993
+ "schema": {
5994
+ "type": "string"
5995
+ },
5996
+ "description": "The `ct_` prefixed claim token from the bootstrap response"
5997
+ }
5998
+ ],
5999
+ "responses": {
6000
+ "200": {
6001
+ "description": "Claim preview",
6002
+ "content": {
6003
+ "application/json": {
6004
+ "schema": {
6005
+ "$ref": "#/components/schemas/ClaimPreviewResponse"
6006
+ }
6007
+ }
6008
+ }
6009
+ },
6010
+ "404": {
6011
+ "description": "Invalid or expired claim token"
6012
+ }
5793
6013
  }
5794
6014
  },
5795
- "PolicyId": {
5796
- "name": "policy_id",
5797
- "in": "path",
5798
- "required": true,
5799
- "schema": {
5800
- "type": "string",
5801
- "format": "uuid"
6015
+ "post": {
6016
+ "tags": [
6017
+ "Platform"
6018
+ ],
6019
+ "summary": "Redeem a claim token",
6020
+ "description": "Redeem a one-time claim token, marking the connection as claimed.\nPublic endpoint — the token itself is the authentication. Returns 409 if already claimed, 410 if expired.\n",
6021
+ "parameters": [
6022
+ {
6023
+ "in": "path",
6024
+ "name": "token",
6025
+ "required": true,
6026
+ "schema": {
6027
+ "type": "string"
6028
+ },
6029
+ "description": "The `ct_` prefixed claim token from the bootstrap response"
6030
+ }
6031
+ ],
6032
+ "responses": {
6033
+ "200": {
6034
+ "description": "Claim redeemed",
6035
+ "content": {
6036
+ "application/json": {
6037
+ "schema": {
6038
+ "$ref": "#/components/schemas/ClaimRedeemResponse"
6039
+ }
6040
+ }
6041
+ }
6042
+ },
6043
+ "404": {
6044
+ "description": "Invalid claim token"
6045
+ },
6046
+ "409": {
6047
+ "description": "Claim token already used"
6048
+ },
6049
+ "410": {
6050
+ "description": "Claim token has expired"
6051
+ }
6052
+ }
6053
+ }
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
+ }
6121
+ }
6122
+ },
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": {
6231
+ "type": "string",
6232
+ "format": "uuid"
6233
+ }
6234
+ },
6235
+ "SecretPath": {
6236
+ "name": "path",
6237
+ "in": "path",
6238
+ "required": true,
6239
+ "schema": {
6240
+ "type": "string"
6241
+ },
6242
+ "description": "Secret path (e.g. \"db/credentials\")"
6243
+ },
6244
+ "AgentId": {
6245
+ "name": "agent_id",
6246
+ "in": "path",
6247
+ "required": true,
6248
+ "schema": {
6249
+ "type": "string",
6250
+ "format": "uuid"
6251
+ }
6252
+ },
6253
+ "PolicyId": {
6254
+ "name": "policy_id",
6255
+ "in": "path",
6256
+ "required": true,
6257
+ "schema": {
6258
+ "type": "string",
6259
+ "format": "uuid"
5802
6260
  }
5803
6261
  },
5804
6262
  "IncludeSignedTx": {
@@ -10660,6 +11118,39 @@
10660
11118
  "type": "string",
10661
11119
  "format": "uuid"
10662
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
+ }
10663
11154
  }
10664
11155
  }
10665
11156
  }
@@ -10700,6 +11191,379 @@
10700
11191
  "format": "date-time"
10701
11192
  }
10702
11193
  }
11194
+ },
11195
+ "ClaimPreviewResponse": {
11196
+ "type": "object",
11197
+ "properties": {
11198
+ "app_name": {
11199
+ "type": "string"
11200
+ },
11201
+ "app_slug": {
11202
+ "type": "string"
11203
+ },
11204
+ "app_logo_url": {
11205
+ "type": "string",
11206
+ "nullable": true
11207
+ },
11208
+ "auth_mode": {
11209
+ "type": "string"
11210
+ },
11211
+ "vault_ids": {
11212
+ "type": "array",
11213
+ "items": {
11214
+ "type": "string",
11215
+ "format": "uuid"
11216
+ }
11217
+ },
11218
+ "agent_ids": {
11219
+ "type": "array",
11220
+ "items": {
11221
+ "type": "string",
11222
+ "format": "uuid"
11223
+ }
11224
+ },
11225
+ "policy_count": {
11226
+ "type": "integer"
11227
+ },
11228
+ "status": {
11229
+ "type": "string"
11230
+ },
11231
+ "already_claimed": {
11232
+ "type": "boolean"
11233
+ },
11234
+ "expired": {
11235
+ "type": "boolean"
11236
+ },
11237
+ "return_to": {
11238
+ "type": "string",
11239
+ "nullable": true
11240
+ }
11241
+ }
11242
+ },
11243
+ "ClaimRedeemResponse": {
11244
+ "type": "object",
11245
+ "properties": {
11246
+ "status": {
11247
+ "type": "string"
11248
+ },
11249
+ "connection_id": {
11250
+ "type": "string",
11251
+ "format": "uuid"
11252
+ },
11253
+ "vault_ids": {
11254
+ "type": "array",
11255
+ "items": {
11256
+ "type": "string",
11257
+ "format": "uuid"
11258
+ }
11259
+ },
11260
+ "agent_ids": {
11261
+ "type": "array",
11262
+ "items": {
11263
+ "type": "string",
11264
+ "format": "uuid"
11265
+ }
11266
+ },
11267
+ "return_to": {
11268
+ "type": "string",
11269
+ "nullable": true
11270
+ },
11271
+ "dashboard_url": {
11272
+ "type": "string"
11273
+ }
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
+ }
10703
11567
  }
10704
11568
  }
10705
11569
  }