@1claw/openapi-spec 0.1.0 → 0.4.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,6 +40,18 @@ openapi-generator generate \
40
40
  import spec from "@1claw/openapi-spec/openapi.json";
41
41
  ```
42
42
 
43
+ ## What's in the spec (v2.1.0)
44
+
45
+ - **Vaults** — CRUD, CMEK enable/disable, key rotation with job tracking
46
+ - **Secrets** — CRUD, versioning, CMEK-encrypted flag
47
+ - **Agents** — CRUD with `auth_method` (api_key, mtls, oidc_client_credentials), auto-generated SSH keypairs, `token_ttl_seconds`, `vault_ids`, crypto proxy, transaction guardrails
48
+ - **Policies** — Glob-based access control
49
+ - **Sharing** — Links, user/agent shares, accept/decline
50
+ - **Billing** — Subscriptions, credits, x402
51
+ - **Audit** — Hash-chained event log
52
+ - **Chains** — Supported blockchain registry
53
+ - **Auth** — JWT, API keys, agent tokens, MFA, device flow, Google OAuth
54
+
43
55
  ## Included files
44
56
 
45
57
  - `openapi.yaml` — The canonical YAML specification
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.0.0",
5
+ "version": "2.1.0",
6
6
  "description": "Secure secret management for AI agents. Provides vaults, secrets,\npolicy-based access control, agent identity, crypto transaction proxy,\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"
@@ -850,6 +850,173 @@
850
850
  }
851
851
  }
852
852
  },
853
+ "/v1/vaults/{vault_id}/cmek": {
854
+ "post": {
855
+ "tags": [
856
+ "CMEK"
857
+ ],
858
+ "summary": "Enable CMEK on a vault",
859
+ "operationId": "enableCmek",
860
+ "description": "Enable client-side encryption on a vault. Requires Business or Enterprise plan.\nOnly the key's SHA-256 fingerprint is stored — the key never touches the server.\n",
861
+ "parameters": [
862
+ {
863
+ "$ref": "#/components/parameters/VaultId"
864
+ }
865
+ ],
866
+ "requestBody": {
867
+ "required": true,
868
+ "content": {
869
+ "application/json": {
870
+ "schema": {
871
+ "$ref": "#/components/schemas/EnableCmekRequest"
872
+ }
873
+ }
874
+ }
875
+ },
876
+ "responses": {
877
+ "200": {
878
+ "description": "CMEK enabled",
879
+ "content": {
880
+ "application/json": {
881
+ "schema": {
882
+ "$ref": "#/components/schemas/VaultResponse"
883
+ }
884
+ }
885
+ }
886
+ },
887
+ "400": {
888
+ "$ref": "#/components/responses/BadRequest"
889
+ },
890
+ "403": {
891
+ "$ref": "#/components/responses/Forbidden"
892
+ }
893
+ }
894
+ },
895
+ "delete": {
896
+ "tags": [
897
+ "CMEK"
898
+ ],
899
+ "summary": "Disable CMEK on a vault",
900
+ "operationId": "disableCmek",
901
+ "description": "Disable client-side encryption. Existing CMEK-encrypted secrets still require\nthe key to decrypt. New secrets will use HSM-only encryption.\n",
902
+ "parameters": [
903
+ {
904
+ "$ref": "#/components/parameters/VaultId"
905
+ }
906
+ ],
907
+ "responses": {
908
+ "200": {
909
+ "description": "CMEK disabled",
910
+ "content": {
911
+ "application/json": {
912
+ "schema": {
913
+ "$ref": "#/components/schemas/VaultResponse"
914
+ }
915
+ }
916
+ }
917
+ },
918
+ "400": {
919
+ "$ref": "#/components/responses/BadRequest"
920
+ }
921
+ }
922
+ }
923
+ },
924
+ "/v1/vaults/{vault_id}/cmek-rotate": {
925
+ "post": {
926
+ "tags": [
927
+ "CMEK"
928
+ ],
929
+ "summary": "Start server-assisted CMEK key rotation",
930
+ "operationId": "rotateCmek",
931
+ "description": "Re-encrypts all secrets from the old CMEK key to the new one.\nKeys are passed in headers (TLS-only) and exist in server memory\nonly during the rotation. Batched in groups of 100 secrets.\n",
932
+ "parameters": [
933
+ {
934
+ "$ref": "#/components/parameters/VaultId"
935
+ },
936
+ {
937
+ "name": "x-cmek-old-key",
938
+ "in": "header",
939
+ "required": true,
940
+ "schema": {
941
+ "type": "string"
942
+ },
943
+ "description": "Base64-encoded old CMEK key (32 bytes)"
944
+ },
945
+ {
946
+ "name": "x-cmek-new-key",
947
+ "in": "header",
948
+ "required": true,
949
+ "schema": {
950
+ "type": "string"
951
+ },
952
+ "description": "Base64-encoded new CMEK key (32 bytes)"
953
+ }
954
+ ],
955
+ "requestBody": {
956
+ "required": true,
957
+ "content": {
958
+ "application/json": {
959
+ "schema": {
960
+ "$ref": "#/components/schemas/CmekRotateRequest"
961
+ }
962
+ }
963
+ }
964
+ },
965
+ "responses": {
966
+ "202": {
967
+ "description": "Rotation job started",
968
+ "content": {
969
+ "application/json": {
970
+ "schema": {
971
+ "$ref": "#/components/schemas/CmekRotationJobResponse"
972
+ }
973
+ }
974
+ }
975
+ },
976
+ "400": {
977
+ "$ref": "#/components/responses/BadRequest"
978
+ }
979
+ }
980
+ }
981
+ },
982
+ "/v1/vaults/{vault_id}/cmek-rotate/{job_id}": {
983
+ "get": {
984
+ "tags": [
985
+ "CMEK"
986
+ ],
987
+ "summary": "Get CMEK rotation job status",
988
+ "operationId": "getCmekRotationJob",
989
+ "parameters": [
990
+ {
991
+ "$ref": "#/components/parameters/VaultId"
992
+ },
993
+ {
994
+ "name": "job_id",
995
+ "in": "path",
996
+ "required": true,
997
+ "schema": {
998
+ "type": "string",
999
+ "format": "uuid"
1000
+ }
1001
+ }
1002
+ ],
1003
+ "responses": {
1004
+ "200": {
1005
+ "description": "Rotation job status",
1006
+ "content": {
1007
+ "application/json": {
1008
+ "schema": {
1009
+ "$ref": "#/components/schemas/CmekRotationJobResponse"
1010
+ }
1011
+ }
1012
+ }
1013
+ },
1014
+ "404": {
1015
+ "$ref": "#/components/responses/NotFound"
1016
+ }
1017
+ }
1018
+ }
1019
+ },
853
1020
  "/v1/vaults/{vault_id}/secrets": {
854
1021
  "get": {
855
1022
  "tags": [
@@ -1311,10 +1478,20 @@
1311
1478
  "Transactions"
1312
1479
  ],
1313
1480
  "summary": "Submit a transaction for signing",
1481
+ "description": "Replay protection: send an optional **Idempotency-Key** header (e.g. UUID or opaque string).\nDuplicate requests with the same key within 24 hours return the cached transaction response\n(no second sign/broadcast). Omit the header for non-idempotent submissions.\n",
1314
1482
  "operationId": "submitTransaction",
1315
1483
  "parameters": [
1316
1484
  {
1317
1485
  "$ref": "#/components/parameters/AgentId"
1486
+ },
1487
+ {
1488
+ "name": "Idempotency-Key",
1489
+ "in": "header",
1490
+ "required": false,
1491
+ "description": "Optional key for replay protection; duplicate requests return cached response.",
1492
+ "schema": {
1493
+ "type": "string"
1494
+ }
1318
1495
  }
1319
1496
  ],
1320
1497
  "requestBody": {
@@ -1328,6 +1505,16 @@
1328
1505
  }
1329
1506
  },
1330
1507
  "responses": {
1508
+ "200": {
1509
+ "description": "Transaction previously created with same Idempotency-Key (replay-safe response)",
1510
+ "content": {
1511
+ "application/json": {
1512
+ "schema": {
1513
+ "$ref": "#/components/schemas/TransactionResponse"
1514
+ }
1515
+ }
1516
+ }
1517
+ },
1331
1518
  "201": {
1332
1519
  "description": "Transaction signed (and optionally broadcast)",
1333
1520
  "content": {
@@ -1341,6 +1528,16 @@
1341
1528
  "403": {
1342
1529
  "$ref": "#/components/responses/Forbidden"
1343
1530
  },
1531
+ "409": {
1532
+ "description": "Idempotency-Key in use by another in-flight request; retry later.",
1533
+ "content": {
1534
+ "application/json": {
1535
+ "schema": {
1536
+ "$ref": "#/components/schemas/ProblemDetails"
1537
+ }
1538
+ }
1539
+ }
1540
+ },
1344
1541
  "422": {
1345
1542
  "description": "Simulation reverted (when simulate_first is true)",
1346
1543
  "content": {
@@ -1362,6 +1559,9 @@
1362
1559
  "parameters": [
1363
1560
  {
1364
1561
  "$ref": "#/components/parameters/AgentId"
1562
+ },
1563
+ {
1564
+ "$ref": "#/components/parameters/IncludeSignedTx"
1365
1565
  }
1366
1566
  ],
1367
1567
  "responses": {
@@ -1397,6 +1597,9 @@
1397
1597
  "type": "string",
1398
1598
  "format": "uuid"
1399
1599
  }
1600
+ },
1601
+ {
1602
+ "$ref": "#/components/parameters/IncludeSignedTx"
1400
1603
  }
1401
1604
  ],
1402
1605
  "responses": {
@@ -2755,6 +2958,16 @@
2755
2958
  "type": "string",
2756
2959
  "format": "uuid"
2757
2960
  }
2961
+ },
2962
+ "IncludeSignedTx": {
2963
+ "name": "include_signed_tx",
2964
+ "in": "query",
2965
+ "required": false,
2966
+ "description": "Set to `true` to include the raw signed transaction hex in the response. Omitted by default to reduce key exfiltration risk.\n",
2967
+ "schema": {
2968
+ "type": "boolean",
2969
+ "default": false
2970
+ }
2758
2971
  }
2759
2972
  },
2760
2973
  "responses": {
@@ -3251,6 +3464,14 @@
3251
3464
  "created_at": {
3252
3465
  "type": "string",
3253
3466
  "format": "date-time"
3467
+ },
3468
+ "cmek_enabled": {
3469
+ "type": "boolean",
3470
+ "description": "Whether client-managed encryption is enabled"
3471
+ },
3472
+ "cmek_fingerprint": {
3473
+ "type": "string",
3474
+ "description": "SHA-256 fingerprint of the CMEK key (64 hex chars)"
3254
3475
  }
3255
3476
  }
3256
3477
  },
@@ -3265,6 +3486,87 @@
3265
3486
  }
3266
3487
  }
3267
3488
  },
3489
+ "EnableCmekRequest": {
3490
+ "type": "object",
3491
+ "required": [
3492
+ "fingerprint"
3493
+ ],
3494
+ "properties": {
3495
+ "fingerprint": {
3496
+ "type": "string",
3497
+ "description": "SHA-256 hex fingerprint of the CMEK key (64 chars)"
3498
+ }
3499
+ }
3500
+ },
3501
+ "CmekRotateRequest": {
3502
+ "type": "object",
3503
+ "required": [
3504
+ "new_fingerprint"
3505
+ ],
3506
+ "properties": {
3507
+ "new_fingerprint": {
3508
+ "type": "string",
3509
+ "description": "SHA-256 hex fingerprint of the new CMEK key"
3510
+ }
3511
+ }
3512
+ },
3513
+ "CmekRotationJobResponse": {
3514
+ "type": "object",
3515
+ "required": [
3516
+ "id",
3517
+ "vault_id",
3518
+ "status",
3519
+ "total_secrets",
3520
+ "processed",
3521
+ "created_at"
3522
+ ],
3523
+ "properties": {
3524
+ "id": {
3525
+ "type": "string",
3526
+ "format": "uuid"
3527
+ },
3528
+ "vault_id": {
3529
+ "type": "string",
3530
+ "format": "uuid"
3531
+ },
3532
+ "old_fingerprint": {
3533
+ "type": "string"
3534
+ },
3535
+ "new_fingerprint": {
3536
+ "type": "string"
3537
+ },
3538
+ "status": {
3539
+ "type": "string",
3540
+ "enum": [
3541
+ "pending",
3542
+ "running",
3543
+ "completed",
3544
+ "failed"
3545
+ ]
3546
+ },
3547
+ "total_secrets": {
3548
+ "type": "integer"
3549
+ },
3550
+ "processed": {
3551
+ "type": "integer"
3552
+ },
3553
+ "error": {
3554
+ "type": "string"
3555
+ },
3556
+ "started_at": {
3557
+ "type": "string",
3558
+ "format": "date-time"
3559
+ },
3560
+ "completed_at": {
3561
+ "type": "string",
3562
+ "format": "date-time"
3563
+ },
3564
+ "created_at": {
3565
+ "type": "string",
3566
+ "format": "date-time"
3567
+ }
3568
+ }
3569
+ },
3268
3570
  "PutSecretRequest": {
3269
3571
  "type": "object",
3270
3572
  "required": [
@@ -3374,6 +3676,10 @@
3374
3676
  "expires_at": {
3375
3677
  "type": "string",
3376
3678
  "format": "date-time"
3679
+ },
3680
+ "cmek_encrypted": {
3681
+ "type": "boolean",
3682
+ "description": "Whether this secret value is CMEK-encrypted (requires client-side decryption)"
3377
3683
  }
3378
3684
  }
3379
3685
  },
@@ -3524,7 +3830,14 @@
3524
3830
  "type": "string"
3525
3831
  },
3526
3832
  "auth_method": {
3527
- "type": "string"
3833
+ "type": "string",
3834
+ "enum": [
3835
+ "api_key",
3836
+ "mtls",
3837
+ "oidc_client_credentials"
3838
+ ],
3839
+ "default": "api_key",
3840
+ "description": "Authentication method. api_key generates a one-time key; mtls requires client_cert_fingerprint; oidc_client_credentials requires oidc_issuer and oidc_client_id."
3528
3841
  },
3529
3842
  "scopes": {
3530
3843
  "type": "array",
@@ -3557,6 +3870,31 @@
3557
3870
  "items": {
3558
3871
  "type": "string"
3559
3872
  }
3873
+ },
3874
+ "token_ttl_seconds": {
3875
+ "type": "integer",
3876
+ "nullable": true,
3877
+ "description": "Per-agent token TTL in seconds (overrides global default)"
3878
+ },
3879
+ "vault_ids": {
3880
+ "type": "array",
3881
+ "items": {
3882
+ "type": "string",
3883
+ "format": "uuid"
3884
+ },
3885
+ "description": "Restrict agent to specific vault UUIDs (empty = all vaults in org)"
3886
+ },
3887
+ "client_cert_fingerprint": {
3888
+ "type": "string",
3889
+ "description": "SHA-256 fingerprint of the client certificate (required for mTLS auth)"
3890
+ },
3891
+ "oidc_issuer": {
3892
+ "type": "string",
3893
+ "description": "OIDC issuer URL (required for oidc_client_credentials auth)"
3894
+ },
3895
+ "oidc_client_id": {
3896
+ "type": "string",
3897
+ "description": "OIDC client ID (required for oidc_client_credentials auth)"
3560
3898
  }
3561
3899
  }
3562
3900
  },
@@ -3599,6 +3937,17 @@
3599
3937
  "items": {
3600
3938
  "type": "string"
3601
3939
  }
3940
+ },
3941
+ "token_ttl_seconds": {
3942
+ "type": "integer",
3943
+ "nullable": true
3944
+ },
3945
+ "vault_ids": {
3946
+ "type": "array",
3947
+ "items": {
3948
+ "type": "string",
3949
+ "format": "uuid"
3950
+ }
3602
3951
  }
3603
3952
  }
3604
3953
  },
@@ -3624,7 +3973,12 @@
3624
3973
  "type": "string"
3625
3974
  },
3626
3975
  "auth_method": {
3627
- "type": "string"
3976
+ "type": "string",
3977
+ "enum": [
3978
+ "api_key",
3979
+ "mtls",
3980
+ "oidc_client_credentials"
3981
+ ]
3628
3982
  },
3629
3983
  "scopes": {
3630
3984
  "type": "array",
@@ -3656,6 +4010,37 @@
3656
4010
  "type": "string"
3657
4011
  }
3658
4012
  },
4013
+ "token_ttl_seconds": {
4014
+ "type": "integer",
4015
+ "nullable": true
4016
+ },
4017
+ "vault_ids": {
4018
+ "type": "array",
4019
+ "items": {
4020
+ "type": "string",
4021
+ "format": "uuid"
4022
+ }
4023
+ },
4024
+ "client_cert_fingerprint": {
4025
+ "type": "string",
4026
+ "description": "SHA-256 fingerprint of the client certificate (mTLS agents)"
4027
+ },
4028
+ "oidc_issuer": {
4029
+ "type": "string",
4030
+ "description": "OIDC issuer URL (oidc_client_credentials agents)"
4031
+ },
4032
+ "oidc_client_id": {
4033
+ "type": "string",
4034
+ "description": "OIDC client ID (oidc_client_credentials agents)"
4035
+ },
4036
+ "ssh_public_key": {
4037
+ "type": "string",
4038
+ "description": "Ed25519 SSH public key (base64-encoded, auto-generated at creation)"
4039
+ },
4040
+ "ecdh_public_key": {
4041
+ "type": "string",
4042
+ "description": "P-256 ECDH public key (base64 SEC1 uncompressed point, auto-generated at creation)"
4043
+ },
3659
4044
  "created_at": {
3660
4045
  "type": "string",
3661
4046
  "format": "date-time"
@@ -3714,14 +4099,21 @@
3714
4099
  "last_active_at": {
3715
4100
  "type": "string",
3716
4101
  "format": "date-time"
4102
+ },
4103
+ "ssh_public_key": {
4104
+ "type": "string",
4105
+ "description": "Ed25519 SSH public key (base64-encoded)"
4106
+ },
4107
+ "ecdh_public_key": {
4108
+ "type": "string",
4109
+ "description": "P-256 ECDH public key (base64 SEC1 uncompressed point)"
3717
4110
  }
3718
4111
  }
3719
4112
  },
3720
4113
  "AgentCreatedResponse": {
3721
4114
  "type": "object",
3722
4115
  "required": [
3723
- "agent",
3724
- "api_key"
4116
+ "agent"
3725
4117
  ],
3726
4118
  "properties": {
3727
4119
  "agent": {
@@ -3729,7 +4121,7 @@
3729
4121
  },
3730
4122
  "api_key": {
3731
4123
  "type": "string",
3732
- "description": "One-time API key (store securely)"
4124
+ "description": "One-time API key (only present for api_key auth method)"
3733
4125
  }
3734
4126
  }
3735
4127
  },
@@ -3876,7 +4268,9 @@
3876
4268
  ]
3877
4269
  },
3878
4270
  "signed_tx": {
3879
- "type": "string"
4271
+ "type": "string",
4272
+ "nullable": true,
4273
+ "description": "Raw signed transaction hex. Omitted (null) by default to reduce exfiltration risk. Pass `include_signed_tx=true` query param on GET endpoints to include it. Always returned on the initial POST submission response.\n"
3880
4274
  },
3881
4275
  "tx_hash": {
3882
4276
  "type": "string"
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.0.0
5
+ version: 2.1.0
6
6
  description: |
7
7
  Secure secret management for AI agents. Provides vaults, secrets,
8
8
  policy-based access control, agent identity, crypto transaction proxy,
@@ -548,6 +548,118 @@ paths:
548
548
  "404":
549
549
  $ref: "#/components/responses/NotFound"
550
550
 
551
+ # ---------------------------------------------------------------------------
552
+ # CMEK (Customer-Managed Encryption Keys)
553
+ # ---------------------------------------------------------------------------
554
+
555
+ /v1/vaults/{vault_id}/cmek:
556
+ post:
557
+ tags: [CMEK]
558
+ summary: Enable CMEK on a vault
559
+ operationId: enableCmek
560
+ description: |
561
+ Enable client-side encryption on a vault. Requires Business or Enterprise plan.
562
+ Only the key's SHA-256 fingerprint is stored — the key never touches the server.
563
+ parameters:
564
+ - $ref: "#/components/parameters/VaultId"
565
+ requestBody:
566
+ required: true
567
+ content:
568
+ application/json:
569
+ schema:
570
+ $ref: "#/components/schemas/EnableCmekRequest"
571
+ responses:
572
+ "200":
573
+ description: CMEK enabled
574
+ content:
575
+ application/json:
576
+ schema:
577
+ $ref: "#/components/schemas/VaultResponse"
578
+ "400":
579
+ $ref: "#/components/responses/BadRequest"
580
+ "403":
581
+ $ref: "#/components/responses/Forbidden"
582
+ delete:
583
+ tags: [CMEK]
584
+ summary: Disable CMEK on a vault
585
+ operationId: disableCmek
586
+ description: |
587
+ Disable client-side encryption. Existing CMEK-encrypted secrets still require
588
+ the key to decrypt. New secrets will use HSM-only encryption.
589
+ parameters:
590
+ - $ref: "#/components/parameters/VaultId"
591
+ responses:
592
+ "200":
593
+ description: CMEK disabled
594
+ content:
595
+ application/json:
596
+ schema:
597
+ $ref: "#/components/schemas/VaultResponse"
598
+ "400":
599
+ $ref: "#/components/responses/BadRequest"
600
+
601
+ /v1/vaults/{vault_id}/cmek-rotate:
602
+ post:
603
+ tags: [CMEK]
604
+ summary: Start server-assisted CMEK key rotation
605
+ operationId: rotateCmek
606
+ description: |
607
+ Re-encrypts all secrets from the old CMEK key to the new one.
608
+ Keys are passed in headers (TLS-only) and exist in server memory
609
+ only during the rotation. Batched in groups of 100 secrets.
610
+ parameters:
611
+ - $ref: "#/components/parameters/VaultId"
612
+ - name: x-cmek-old-key
613
+ in: header
614
+ required: true
615
+ schema:
616
+ type: string
617
+ description: Base64-encoded old CMEK key (32 bytes)
618
+ - name: x-cmek-new-key
619
+ in: header
620
+ required: true
621
+ schema:
622
+ type: string
623
+ description: Base64-encoded new CMEK key (32 bytes)
624
+ requestBody:
625
+ required: true
626
+ content:
627
+ application/json:
628
+ schema:
629
+ $ref: "#/components/schemas/CmekRotateRequest"
630
+ responses:
631
+ "202":
632
+ description: Rotation job started
633
+ content:
634
+ application/json:
635
+ schema:
636
+ $ref: "#/components/schemas/CmekRotationJobResponse"
637
+ "400":
638
+ $ref: "#/components/responses/BadRequest"
639
+
640
+ /v1/vaults/{vault_id}/cmek-rotate/{job_id}:
641
+ get:
642
+ tags: [CMEK]
643
+ summary: Get CMEK rotation job status
644
+ operationId: getCmekRotationJob
645
+ parameters:
646
+ - $ref: "#/components/parameters/VaultId"
647
+ - name: job_id
648
+ in: path
649
+ required: true
650
+ schema:
651
+ type: string
652
+ format: uuid
653
+ responses:
654
+ "200":
655
+ description: Rotation job status
656
+ content:
657
+ application/json:
658
+ schema:
659
+ $ref: "#/components/schemas/CmekRotationJobResponse"
660
+ "404":
661
+ $ref: "#/components/responses/NotFound"
662
+
551
663
  # ---------------------------------------------------------------------------
552
664
  # Secrets
553
665
  # ---------------------------------------------------------------------------
@@ -829,9 +941,19 @@ paths:
829
941
  post:
830
942
  tags: [Transactions]
831
943
  summary: Submit a transaction for signing
944
+ description: |
945
+ Replay protection: send an optional **Idempotency-Key** header (e.g. UUID or opaque string).
946
+ Duplicate requests with the same key within 24 hours return the cached transaction response
947
+ (no second sign/broadcast). Omit the header for non-idempotent submissions.
832
948
  operationId: submitTransaction
833
949
  parameters:
834
950
  - $ref: "#/components/parameters/AgentId"
951
+ - name: Idempotency-Key
952
+ in: header
953
+ required: false
954
+ description: Optional key for replay protection; duplicate requests return cached response.
955
+ schema:
956
+ type: string
835
957
  requestBody:
836
958
  required: true
837
959
  content:
@@ -845,8 +967,20 @@ paths:
845
967
  application/json:
846
968
  schema:
847
969
  $ref: "#/components/schemas/TransactionResponse"
970
+ "200":
971
+ description: Transaction previously created with same Idempotency-Key (replay-safe response)
972
+ content:
973
+ application/json:
974
+ schema:
975
+ $ref: "#/components/schemas/TransactionResponse"
848
976
  "403":
849
977
  $ref: "#/components/responses/Forbidden"
978
+ "409":
979
+ description: Idempotency-Key in use by another in-flight request; retry later.
980
+ content:
981
+ application/json:
982
+ schema:
983
+ $ref: "#/components/schemas/ProblemDetails"
850
984
  "422":
851
985
  description: Simulation reverted (when simulate_first is true)
852
986
  content:
@@ -859,6 +993,7 @@ paths:
859
993
  operationId: listTransactions
860
994
  parameters:
861
995
  - $ref: "#/components/parameters/AgentId"
996
+ - $ref: "#/components/parameters/IncludeSignedTx"
862
997
  responses:
863
998
  "200":
864
999
  description: Transaction list
@@ -880,6 +1015,7 @@ paths:
880
1015
  schema:
881
1016
  type: string
882
1017
  format: uuid
1018
+ - $ref: "#/components/parameters/IncludeSignedTx"
883
1019
  responses:
884
1020
  "200":
885
1021
  description: Transaction details
@@ -1759,6 +1895,16 @@ components:
1759
1895
  schema:
1760
1896
  type: string
1761
1897
  format: uuid
1898
+ IncludeSignedTx:
1899
+ name: include_signed_tx
1900
+ in: query
1901
+ required: false
1902
+ description: >
1903
+ Set to `true` to include the raw signed transaction hex in the response.
1904
+ Omitted by default to reduce key exfiltration risk.
1905
+ schema:
1906
+ type: boolean
1907
+ default: false
1762
1908
 
1763
1909
  responses:
1764
1910
  BadRequest:
@@ -2101,6 +2247,12 @@ components:
2101
2247
  created_at:
2102
2248
  type: string
2103
2249
  format: date-time
2250
+ cmek_enabled:
2251
+ type: boolean
2252
+ description: Whether client-managed encryption is enabled
2253
+ cmek_fingerprint:
2254
+ type: string
2255
+ description: SHA-256 fingerprint of the CMEK key (64 hex chars)
2104
2256
 
2105
2257
  VaultListResponse:
2106
2258
  type: object
@@ -2110,6 +2262,57 @@ components:
2110
2262
  items:
2111
2263
  $ref: "#/components/schemas/VaultResponse"
2112
2264
 
2265
+ # --- CMEK ---
2266
+
2267
+ EnableCmekRequest:
2268
+ type: object
2269
+ required: [fingerprint]
2270
+ properties:
2271
+ fingerprint:
2272
+ type: string
2273
+ description: SHA-256 hex fingerprint of the CMEK key (64 chars)
2274
+
2275
+ CmekRotateRequest:
2276
+ type: object
2277
+ required: [new_fingerprint]
2278
+ properties:
2279
+ new_fingerprint:
2280
+ type: string
2281
+ description: SHA-256 hex fingerprint of the new CMEK key
2282
+
2283
+ CmekRotationJobResponse:
2284
+ type: object
2285
+ required: [id, vault_id, status, total_secrets, processed, created_at]
2286
+ properties:
2287
+ id:
2288
+ type: string
2289
+ format: uuid
2290
+ vault_id:
2291
+ type: string
2292
+ format: uuid
2293
+ old_fingerprint:
2294
+ type: string
2295
+ new_fingerprint:
2296
+ type: string
2297
+ status:
2298
+ type: string
2299
+ enum: [pending, running, completed, failed]
2300
+ total_secrets:
2301
+ type: integer
2302
+ processed:
2303
+ type: integer
2304
+ error:
2305
+ type: string
2306
+ started_at:
2307
+ type: string
2308
+ format: date-time
2309
+ completed_at:
2310
+ type: string
2311
+ format: date-time
2312
+ created_at:
2313
+ type: string
2314
+ format: date-time
2315
+
2113
2316
  # --- Secrets ---
2114
2317
 
2115
2318
  PutSecretRequest:
@@ -2183,6 +2386,9 @@ components:
2183
2386
  expires_at:
2184
2387
  type: string
2185
2388
  format: date-time
2389
+ cmek_encrypted:
2390
+ type: boolean
2391
+ description: Whether this secret value is CMEK-encrypted (requires client-side decryption)
2186
2392
 
2187
2393
  SecretListResponse:
2188
2394
  type: object
@@ -2284,6 +2490,9 @@ components:
2284
2490
  type: string
2285
2491
  auth_method:
2286
2492
  type: string
2493
+ enum: [api_key, mtls, oidc_client_credentials]
2494
+ default: api_key
2495
+ description: Authentication method. api_key generates a one-time key; mtls requires client_cert_fingerprint; oidc_client_credentials requires oidc_issuer and oidc_client_id.
2287
2496
  scopes:
2288
2497
  type: array
2289
2498
  items:
@@ -2306,6 +2515,25 @@ components:
2306
2515
  type: array
2307
2516
  items:
2308
2517
  type: string
2518
+ token_ttl_seconds:
2519
+ type: integer
2520
+ nullable: true
2521
+ description: Per-agent token TTL in seconds (overrides global default)
2522
+ vault_ids:
2523
+ type: array
2524
+ items:
2525
+ type: string
2526
+ format: uuid
2527
+ description: Restrict agent to specific vault UUIDs (empty = all vaults in org)
2528
+ client_cert_fingerprint:
2529
+ type: string
2530
+ description: SHA-256 fingerprint of the client certificate (required for mTLS auth)
2531
+ oidc_issuer:
2532
+ type: string
2533
+ description: OIDC issuer URL (required for oidc_client_credentials auth)
2534
+ oidc_client_id:
2535
+ type: string
2536
+ description: OIDC client ID (required for oidc_client_credentials auth)
2309
2537
 
2310
2538
  UpdateAgentRequest:
2311
2539
  type: object
@@ -2335,6 +2563,14 @@ components:
2335
2563
  type: array
2336
2564
  items:
2337
2565
  type: string
2566
+ token_ttl_seconds:
2567
+ type: integer
2568
+ nullable: true
2569
+ vault_ids:
2570
+ type: array
2571
+ items:
2572
+ type: string
2573
+ format: uuid
2338
2574
 
2339
2575
  AgentResponse:
2340
2576
  type: object
@@ -2349,6 +2585,7 @@ components:
2349
2585
  type: string
2350
2586
  auth_method:
2351
2587
  type: string
2588
+ enum: [api_key, mtls, oidc_client_credentials]
2352
2589
  scopes:
2353
2590
  type: array
2354
2591
  items:
@@ -2369,6 +2606,29 @@ components:
2369
2606
  type: array
2370
2607
  items:
2371
2608
  type: string
2609
+ token_ttl_seconds:
2610
+ type: integer
2611
+ nullable: true
2612
+ vault_ids:
2613
+ type: array
2614
+ items:
2615
+ type: string
2616
+ format: uuid
2617
+ client_cert_fingerprint:
2618
+ type: string
2619
+ description: SHA-256 fingerprint of the client certificate (mTLS agents)
2620
+ oidc_issuer:
2621
+ type: string
2622
+ description: OIDC issuer URL (oidc_client_credentials agents)
2623
+ oidc_client_id:
2624
+ type: string
2625
+ description: OIDC client ID (oidc_client_credentials agents)
2626
+ ssh_public_key:
2627
+ type: string
2628
+ description: Ed25519 SSH public key (base64-encoded, auto-generated at creation)
2629
+ ecdh_public_key:
2630
+ type: string
2631
+ description: P-256 ECDH public key (base64 SEC1 uncompressed point, auto-generated at creation)
2372
2632
  created_at:
2373
2633
  type: string
2374
2634
  format: date-time
@@ -2412,16 +2672,22 @@ components:
2412
2672
  last_active_at:
2413
2673
  type: string
2414
2674
  format: date-time
2675
+ ssh_public_key:
2676
+ type: string
2677
+ description: Ed25519 SSH public key (base64-encoded)
2678
+ ecdh_public_key:
2679
+ type: string
2680
+ description: P-256 ECDH public key (base64 SEC1 uncompressed point)
2415
2681
 
2416
2682
  AgentCreatedResponse:
2417
2683
  type: object
2418
- required: [agent, api_key]
2684
+ required: [agent]
2419
2685
  properties:
2420
2686
  agent:
2421
2687
  $ref: "#/components/schemas/AgentResponse"
2422
2688
  api_key:
2423
2689
  type: string
2424
- description: One-time API key (store securely)
2690
+ description: One-time API key (only present for api_key auth method)
2425
2691
 
2426
2692
  AgentListResponse:
2427
2693
  type: object
@@ -2519,6 +2785,11 @@ components:
2519
2785
  enum: [pending, signed, broadcast, failed, simulation_failed]
2520
2786
  signed_tx:
2521
2787
  type: string
2788
+ nullable: true
2789
+ description: >
2790
+ Raw signed transaction hex. Omitted (null) by default to reduce exfiltration risk.
2791
+ Pass `include_signed_tx=true` query param on GET endpoints to include it.
2792
+ Always returned on the initial POST submission response.
2522
2793
  tx_hash:
2523
2794
  type: string
2524
2795
  error_message:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1claw/openapi-spec",
3
- "version": "0.1.0",
3
+ "version": "0.4.0",
4
4
  "description": "OpenAPI 3.1.0 specification for the 1Claw Vault API — generate clients in any language",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "repository": {