{
  "openapi": "3.1.0",
  "info": {
    "title": "StoneAI API",
    "version": "0.8.0",
    "description": "StoneAI — the Covenant Engine. Every AI decision becomes a decree: proposed by a model council, gated by human approval scopes, sealed into a hash-chained audit ledger, and provable offline via signed Covenant Receipts.\n\nAll `/v1/*` JSON responses are wrapped in a uniform envelope: `{ success: true, data: ... }` on 2xx and `{ success: false, error, message }` on errors. Routes outside `/v1` (like `/health`) return raw JSON; `/proof/*` returns HTML.",
    "contact": { "name": "StoneAI", "url": "https://writteninstone.io" }
  },
  "servers": [{ "url": "https://writteninstone.io" }],
  "tags": [
    { "name": "System", "description": "Health and live status probes." },
    { "name": "Auth", "description": "Signup, login, sessions, email verification, password reset." },
    { "name": "Decrees", "description": "The core engine: raise, list, approve, deny, and prove decrees." },
    { "name": "Governance", "description": "Audit ledger, stats, fleet, usage, and public proof surfaces." },
    { "name": "Billing", "description": "Plans, billing state, and checkout." },
    { "name": "Account", "description": "API keys, team, and outbound webhook configuration." },
    { "name": "Inbound Webhooks", "description": "Signature-verified processor callbacks (server-to-server)." }
  ],
  "security": [{ "bearerAuth": [] }, { "cookieAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Tenant API key issued at signup or via POST /v1/keys. Send as `Authorization: Bearer <key>`."
      },
      "cookieAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "stoneai_sess",
        "description": "httpOnly signed session cookie set by POST /v1/login."
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "description": "Uniform success envelope for every /v1 2xx JSON response.",
        "required": ["success", "data"],
        "properties": {
          "success": { "const": true },
          "data": { "description": "Route-specific payload (documented per operation)." }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "description": "Uniform error envelope for every /v1 4xx/5xx JSON response.",
        "required": ["success", "error", "message"],
        "properties": {
          "success": { "const": false },
          "error": { "type": "string", "examples": ["not_found", "rate_limited", "unauthorized"] },
          "message": { "type": "string" }
        }
      },
      "Decree": {
        "type": "object",
        "description": "A governed decision produced by the council from a submitted truth.",
        "properties": {
          "id": { "type": "string" },
          "action": { "type": "string", "description": "Council-chosen action (e.g. rollback, restart, escalate)." },
          "target": { "type": "string" },
          "reasoning": { "type": "string" },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "required_scope": { "type": "string", "description": "Approval scope a human must present (e.g. PRODUCTION)." },
          "content_hash": { "type": "string", "description": "SHA-256 over the decree content; chained into the audit ledger." },
          "status": { "type": "string", "enum": ["pending", "approved", "denied"] }
        }
      },
      "Receipt": {
        "type": "object",
        "description": "Covenant Receipt — an offline-verifiable, Ed25519-signed proof that a decision was governed. Verify with `npx @stoneai/verify receipt.json`.",
        "properties": {
          "v": { "type": "integer", "description": "Receipt format version." },
          "tenantId": { "type": "string" },
          "decreeId": { "type": "string" },
          "contentHash": { "type": "string" },
          "decision": { "type": "string", "enum": ["approved", "denied"] },
          "approval": {
            "type": "object",
            "description": "Who approved/denied, with what scope, and when.",
            "properties": {
              "approverId": { "type": "string" },
              "scope": { "type": "string" },
              "at": { "type": "string", "format": "date-time" }
            }
          },
          "pubKey": { "type": "string", "description": "Base64 Ed25519 public key that signs this receipt." },
          "chain": {
            "type": "object",
            "description": "Hash-chain linkage of the audit entries covering this decree.",
            "properties": {
              "prevHash": { "type": "string" },
              "entryHash": { "type": "string" }
            }
          },
          "anchor": {
            "description": "Latest ledger anchor covering this entry (null until the anchor job passes).",
            "type": ["object", "null"]
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "priceUsd": { "type": "number" },
          "includedDecrees": { "type": "integer" }
        }
      },
      "ApiKey": {
        "type": "object",
        "description": "API key metadata. The raw key is returned ONCE at creation and never stored.",
        "properties": {
          "id": { "type": "string" },
          "label": { "type": "string" },
          "prefix": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "StatusReport": {
        "type": "object",
        "description": "Live status. Every number is a real probe result — uptime is since process boot, never cumulative.",
        "properties": {
          "db": {
            "type": "object",
            "properties": { "ok": { "type": "boolean" }, "latencyMs": { "type": "number" } }
          },
          "council": {
            "type": "object",
            "properties": { "mode": { "type": "string", "enum": ["live", "stub"] } }
          },
          "anchors": {
            "type": "object",
            "properties": {
              "available": { "type": "boolean" },
              "lastAt": { "type": ["string", "null"], "format": "date-time" },
              "ageMinutes": { "type": ["number", "null"] }
            }
          },
          "uptimeSeconds": { "type": "number" },
          "version": { "type": "string" },
          "probes": {
            "type": "array",
            "maxItems": 60,
            "items": {
              "type": "object",
              "properties": {
                "ts": { "type": "string", "format": "date-time" },
                "dbOk": { "type": "boolean" },
                "latencyMs": { "type": "number" }
              }
            }
          }
        }
      }
    },
    "responses": {
      "Enveloped": {
        "description": "Success (enveloped).",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Envelope" } } }
      },
      "Error": {
        "description": "Error (enveloped).",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } } }
      }
    }
  },
  "paths": {
    "/health": {
      "get": {
        "tags": ["System"],
        "summary": "Liveness probe (raw JSON, not enveloped)",
        "security": [],
        "responses": {
          "200": {
            "description": "Service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "status": { "const": "ok" }, "service": { "const": "stoneai" } }
                }
              }
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "tags": ["System"],
        "summary": "Live status report (public, no auth)",
        "security": [],
        "responses": {
          "200": {
            "description": "Enveloped StatusReport.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "$ref": "#/components/schemas/StatusReport" } } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup": {
      "post": {
        "tags": ["Auth"],
        "summary": "Create a tenant + owner account",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email", "password", "company"],
                "properties": {
                  "email": { "type": "string", "format": "email" },
                  "password": { "type": "string", "minLength": 10 },
                  "company": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tenant created. The apiKey is shown ONCE — store it now.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "tenantId": { "type": "string" },
                            "apiKey": { "type": "string" },
                            "signingPubKey": { "type": "string", "description": "Base64 Ed25519 key for offline receipt verification." },
                            "verifyEmailSent": { "type": "boolean" }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Log in (sets stoneai_sess cookie)",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email", "password"],
                "properties": { "email": { "type": "string" }, "password": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "End the current session",
        "security": [{ "cookieAuth": [] }],
        "responses": { "200": { "$ref": "#/components/responses/Enveloped" } }
      }
    },
    "/v1/me": {
      "get": {
        "tags": ["Auth"],
        "summary": "Current user + tenant",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/password-reset/request": {
      "post": {
        "tags": ["Auth"],
        "summary": "Request a password-reset email",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string" } } }
            }
          }
        },
        "responses": { "200": { "description": "Always 200 (no account enumeration).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Envelope" } } } } }
      }
    },
    "/v1/password-reset/confirm": {
      "post": {
        "tags": ["Auth"],
        "summary": "Set a new password with a reset token",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["token", "password"],
                "properties": { "token": { "type": "string" }, "password": { "type": "string", "minLength": 10 } }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "400": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/verify-email": {
      "get": {
        "tags": ["Auth"],
        "summary": "Verify an email address",
        "security": [],
        "parameters": [
          { "name": "token", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "400": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/decrees": {
      "post": {
        "tags": ["Decrees"],
        "summary": "Raise a decree from a truth",
        "description": "Submit a truth (any JSON facts). The council reasons over it and returns a decree pending human approval.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["domain", "truth"],
                "properties": {
                  "domain": { "type": "string", "examples": ["ops", "finance", "content"] },
                  "truth": { "type": "object", "description": "Arbitrary facts the council reasons over." }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Decree created (status: pending).",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "$ref": "#/components/schemas/Decree" } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "402": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      },
      "get": {
        "tags": ["Decrees"],
        "summary": "List decrees (last 50)",
        "responses": {
          "200": {
            "description": "Enveloped array of Decree.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Decree" } } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/decrees/{id}/approve": {
      "post": {
        "tags": ["Decrees"],
        "summary": "Approve a decree with a scope",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["approverId", "scope"],
                "properties": {
                  "approverId": { "type": "string" },
                  "scope": { "type": "string", "description": "Must satisfy the decree's required_scope." }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/decrees/{id}/deny": {
      "post": {
        "tags": ["Decrees"],
        "summary": "Deny a decree",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/decrees/{id}/receipt": {
      "get": {
        "tags": ["Decrees"],
        "summary": "Covenant Receipt for a decided decree",
        "description": "Signed, offline-verifiable proof. Verify without trusting StoneAI: `npx @stoneai/verify receipt.json --pubkey <signingPubKey>`.",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "Enveloped Receipt.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "$ref": "#/components/schemas/Receipt" } } }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/audit": {
      "get": {
        "tags": ["Governance"],
        "summary": "Hash-chained audit ledger entries",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "tags": ["Governance"],
        "summary": "Tenant decision stats (live counts)",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/fleet": {
      "get": {
        "tags": ["Governance"],
        "summary": "Governed fleet overview",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "tags": ["Governance"],
        "summary": "Metered usage for the current period",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/governance/public": {
      "get": {
        "tags": ["Governance"],
        "summary": "Public governance transparency feed (no auth)",
        "security": [],
        "responses": { "200": { "$ref": "#/components/responses/Enveloped" } }
      }
    },
    "/proof/{tenantId}/{decreeId}": {
      "get": {
        "tags": ["Governance"],
        "summary": "Public proof page (HTML) for a decided decree",
        "security": [],
        "parameters": [
          { "name": "tenantId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "decreeId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Human-readable proof page.", "content": { "text/html": { "schema": { "type": "string" } } } },
          "404": { "description": "Unknown proof.", "content": { "text/html": { "schema": { "type": "string" } } } }
        }
      }
    },
    "/v1/plans": {
      "get": {
        "tags": ["Billing"],
        "summary": "Available plans",
        "security": [],
        "responses": {
          "200": {
            "description": "Enveloped array of Plan.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Plan" } } } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing": {
      "get": {
        "tags": ["Billing"],
        "summary": "Current billing state for the tenant",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/checkout/methods": {
      "get": {
        "tags": ["Billing"],
        "summary": "Enabled payment methods",
        "responses": { "200": { "$ref": "#/components/responses/Enveloped" } }
      }
    },
    "/v1/checkout/session": {
      "post": {
        "tags": ["Billing"],
        "summary": "Create a hosted checkout session",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["method", "plan"],
                "properties": {
                  "method": { "type": "string", "enum": ["stripe", "paypal", "crypto"] },
                  "plan": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/keys": {
      "get": {
        "tags": ["Account"],
        "summary": "List API keys (metadata only)",
        "responses": {
          "200": {
            "description": "Enveloped array of ApiKey.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ApiKey" } } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Error" }
        }
      },
      "post": {
        "tags": ["Account"],
        "summary": "Create an API key (raw key returned once)",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "label": { "type": "string" } } }
            }
          }
        },
        "responses": {
          "201": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/keys/{id}": {
      "delete": {
        "tags": ["Account"],
        "summary": "Revoke an API key",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "404": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/team": {
      "get": {
        "tags": ["Account"],
        "summary": "List team members",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/team/invite": {
      "post": {
        "tags": ["Account"],
        "summary": "Invite a team member",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email"],
                "properties": { "email": { "type": "string" }, "role": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/team/accept": {
      "post": {
        "tags": ["Account"],
        "summary": "Accept a team invite",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["token", "password"],
                "properties": { "token": { "type": "string" }, "password": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "400": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/webhook": {
      "get": {
        "tags": ["Account"],
        "summary": "Current outbound webhook config",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      },
      "put": {
        "tags": ["Account"],
        "summary": "Set the outbound webhook (decree events, HMAC-signed)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["url"],
                "properties": {
                  "url": { "type": "string", "format": "uri" },
                  "events": { "type": "array", "items": { "type": "string" } }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "400": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/webhook/deliveries": {
      "get": {
        "tags": ["Account"],
        "summary": "Recent outbound webhook delivery attempts",
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/webhooks/stripe": {
      "post": {
        "tags": ["Inbound Webhooks"],
        "summary": "Stripe events (signature-verified, fail-closed)",
        "security": [],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/webhooks/paypal": {
      "post": {
        "tags": ["Inbound Webhooks"],
        "summary": "PayPal events (signature-verified, fail-closed)",
        "security": [],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/v1/webhooks/coinbase": {
      "post": {
        "tags": ["Inbound Webhooks"],
        "summary": "Coinbase Commerce events (signature-verified, fail-closed)",
        "security": [],
        "responses": {
          "200": { "$ref": "#/components/responses/Enveloped" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  }
}
