diff --git a/site/developers.html b/site/developers.html new file mode 100644 index 0000000..6b3a305 --- /dev/null +++ b/site/developers.html @@ -0,0 +1,268 @@ + + + + + +Application Client · Developers + + + + + + + + +
+ Verae + +
+
+
+

Application Client · OpenAPI

+

Build without an AI host

+

Stamp, verify, and look up digests from Python, TypeScript, or raw HTTP. Paths in the OpenAPI file are logical SDK operations — not deployed REST routes on this host. File bytes never leave the client; only SHA-256 digests are sent.

+
+
+
+
+

Overview

+

The Application Client routes by scope: global hits VeraeTime directly; local / shared use MCP Streamable HTTP at /mcp. SDKs refuse content-byte argument names (content, bytes, file, data, path, body, payload, blob, archive).

+ +
+ +
+

Transport split

+

One Application API surface; two backends. Auth ops always use VeraeTime with a caller-held JWT.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operationlocal / sharedglobal
stampMCP tool stampVeraeTime POST /api/timestamp
verifyMCP tool verifyVeraeTime POST /api/verify
hash_reportMCP tool hash_reportVeraeTime GET /api/hash/{sha256}
signup / login / session / create_userVeraeTime /auth/* (direct; apps do not rely on MCP account tools)
+
+ +
+

OpenAPI

+

Normative digests-only contract for the Application Client SDKs (OpenAPI 3.1). Download or fetch from this site:

+
https://mcp.verae.ai/openapi/application-client.yaml
+ +

Logical paths such as /stamp document SDK methods; they are not HTTP routes on mcp.verae.ai in this phase.

+
+ +
+

Python

+

Package verae-mcp-timestamping-client — ApplicationClient routes by scope.

+
import asyncio
+from verae_mcp_timestamping_client import ApplicationClient
+
+async def main():
+    client = ApplicationClient()
+    print(await client.stamp("<64-hex>", scope="global"))
+    print(await client.stamp("<64-hex>", scope="local"))
+
+asyncio.run(main())
+

Install: uv add verae-mcp-timestamping-client or pip install verae-mcp-timestamping-client.

+
+ +
+

TypeScript

+

Package @verae/timestamping-client. Method names are camelCase (hashReport); OpenAPI stays snake_case.

+
import { ApplicationClient } from "@verae/timestamping-client";
+
+const client = new ApplicationClient({ token: process.env.VERAE_GLOBAL_TOKEN });
+
+// Global → VeraeTime POST /api/timestamp (restamp: false)
+const global = await client.stamp("a".repeat(64), { scope: "global" });
+
+// Local → MCP tools/call stamp
+const local = await client.stamp("a".repeat(64), { scope: "local" });
+

Install: npm install @verae/timestamping-client.

+
+ +
+

curl · global (VeraeTime)

+

Direct HTTPS to api.veraetime.net. Bearer token from env or ~/.verae/auth.properties.

+
# TOKEN from VERAE_GLOBAL_TOKEN or access_token in ~/.verae/auth.properties
+DIGEST=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+
+curl -sS -X POST https://api.veraetime.net/api/timestamp \
+  -H 'Content-Type: application/json' \
+  -H 'Accept: application/json' \
+  -H "Authorization: Bearer $TOKEN" \
+  -d "{\"data\":\"$DIGEST\",\"digest\":\"$DIGEST\",\"hashAlg\":\"SHA256\",\"restamp\":false}"
+

On 200 with certificate / existing, reuse that CID. Otherwise poll GET /api/status/{jobId}.

+
+ +
+

curl · MCP local

+

Streamable HTTP at /mcp. Capture Mcp-Session-Id from initialize, then notifications/initialized, then tools/call.

+
# 1) initialize — note Mcp-Session-Id in response headers
+curl -sS -D - -X POST https://mcp.verae.ai/mcp \
+  -H 'Content-Type: application/json' \
+  -H 'Accept: application/json, text/event-stream' \
+  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"dev-curl","version":"1.0.0"}}}'
+
+# 2) notifications/initialized (same session)
+curl -sS -X POST https://mcp.verae.ai/mcp \
+  -H 'Content-Type: application/json' \
+  -H 'Accept: application/json, text/event-stream' \
+  -H 'Mcp-Session-Id: SESSION' \
+  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
+
+# 3) tools/call stamp (local scope)
+curl -sS -X POST https://mcp.verae.ai/mcp \
+  -H 'Content-Type: application/json' \
+  -H 'Accept: application/json, text/event-stream' \
+  -H 'Mcp-Session-Id: SESSION' \
+  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"stamp","arguments":{"sha256":"DIGEST_HEX","scope":"local"}}}'
+
+ +
+

Auth

+

Machine login writes a JWT under ~/.verae/auth.properties (mode 600). Do not paste tokens into chat or commit the file.

+
+

Resolve order (Application Client / VeraeTime transport): constructor token → VERAE_GLOBAL_TOKEN → access_token / auth_token / id_token in auth.properties (VERAE_AUTH_PROPERTIES overrides the path).

+
uvx verae-mcp-timestamping-server setup
+# writes ~/.verae/auth.properties (mode 600); does not print the token
+uvx verae-mcp-timestamping-server session
+

Keys typically include access_token, expires_at, and username. Directory ~/.verae is mode 700.

+
+
+
+
+ + + diff --git a/site/index.html b/site/index.html index 5acf21d..264f971 100644 --- a/site/index.html +++ b/site/index.html @@ -168,6 +168,8 @@ Hasher Connect Register + Ways to use + Developers Try a stamp diff --git a/site/openapi/application-client.yaml b/site/openapi/application-client.yaml new file mode 100644 index 0000000..8d04f67 --- /dev/null +++ b/site/openapi/application-client.yaml @@ -0,0 +1,374 @@ +openapi: 3.1.0 +info: + title: Verae Application Client API + version: 0.1.0 + description: | + Digests-only Application Client API for non-AI apps. Paths below are **logical** + documentation identifiers for the client SDKs (Python / TypeScript); they are **not** + deployed server routes on `mcp.verae.ai` in this phase. + + **Defaults:** MCP Streamable HTTP `https://mcp.verae.ai/mcp`; VeraeTime + `https://api.veraetime.net`. + + **Digests only:** stamp / verify / hash_report accept SHA-256 digests. SDKs refuse + arguments named `content`, `bytes`, `file`, `data`, `path`, `body`, `payload`, + `blob`, or `archive`. + + **Global stamp:** VeraeTime body uses `restamp: false` by default (reuse existing + certificate). Explicit restamp is out of scope unless added later. + + ## Mapping appendix (MCP ↔ VeraeTime ↔ Application API) + + | Application op | MCP tool | VeraeTime | + | --- | --- | --- | + | stamp local/shared | `stamp` | — | + | stamp global | — | `POST /api/timestamp` | + | verify (non-global) | `verify` | — | + | verify global | — | `POST /api/verify` | + | hash_report (non-global) | `hash_report` | — | + | hash_report global | — | `GET /api/hash/{sha256}` | + | signup | (`signup` exists on MCP; apps use direct) | `POST /auth/signup` | + | login | (`login` exists on MCP; apps use direct) | `POST /auth/login` | + | session | (`session` exists on MCP; apps use direct) | `GET /auth/validate` | + | create_user | (`create_user` exists on MCP; apps use direct) | `POST /auth/users` | + + Routing: `local` / `shared` stamp and non-global verify / hash_report use MCP. + `global` / `want_scope=global` use VeraeTime directly. Auth ops always hit VeraeTime + with caller-held JWTs. +servers: + - url: https://mcp.verae.ai + description: > + Logical base for documentation only. Application Client SDK paths are not + deployed HTTP routes; local/shared ops use MCP at https://mcp.verae.ai/mcp. + - url: https://api.veraetime.net + description: > + VeraeTime direct HTTPS for global stamp/verify/hash_report and all auth ops. + Application Client paths still map to /api/* and /auth/* as in the appendix. +paths: + /stamp: + post: + operationId: stamp + summary: Stamp a SHA-256 digest + description: | + Request a timestamp for a digest. Scope `local` or `shared` goes to MCP tool + `stamp`; scope `global` goes to VeraeTime `POST /api/timestamp` with + `restamp: false` by default. + tags: [timestamping] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/StampRequest" + responses: + "200": + description: One or more normalized receipts + content: + application/json: + schema: + $ref: "#/components/schemas/StampResponse" + /verify: + post: + operationId: verify + summary: Verify a receipt + description: | + Verify by `receipt_id`. Use `want_scope=global` (or a global receipt) for + VeraeTime `POST /api/verify`; otherwise MCP tool `verify`. + tags: [timestamping] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/VerifyRequest" + responses: + "200": + description: Verification result + content: + application/json: + schema: + $ref: "#/components/schemas/VerifyResponse" + /hash_report: + post: + operationId: hash_report + summary: List receipts for a digest + description: | + History for a SHA-256 digest. `want_scope=global` uses VeraeTime + `GET /api/hash/{sha256}`; otherwise MCP tool `hash_report`. Empty history + is `{ "receipts": [] }`. + tags: [timestamping] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/HashReportRequest" + responses: + "200": + description: Receipts for the digest (possibly empty) + content: + application/json: + schema: + $ref: "#/components/schemas/HashReportResponse" + /signup: + post: + operationId: signup + summary: Create an account on VeraeTime + description: | + Always `POST https://api.veraetime.net/auth/signup`. Does not replace the + stored JWT; caller must `login` for a session. + tags: [auth] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SignupRequest" + responses: + "200": + description: Created user + content: + application/json: + schema: + $ref: "#/components/schemas/AuthUserResponse" + /login: + post: + operationId: login + summary: Login and obtain caller-held JWT + description: | + Always `POST https://api.veraetime.net/auth/login`. SDK stores JWT in + caller-local secure storage (`~/.verae/auth.properties` on native). JWT + values are never logged. + tags: [auth] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LoginRequest" + responses: + "200": + description: Authenticated user session metadata + content: + application/json: + schema: + $ref: "#/components/schemas/AuthUserResponse" + /session: + get: + operationId: session + summary: Validate current session + description: | + Always `GET https://api.veraetime.net/auth/validate` with bearer from + constructor, `VERAE_GLOBAL_TOKEN`, or auth.properties. + tags: [auth] + security: + - bearerAuth: [] + responses: + "200": + description: Session validity + content: + application/json: + schema: + $ref: "#/components/schemas/SessionResponse" + /create_user: + post: + operationId: create_user + summary: Create a user (admin) + description: | + Always `POST https://api.veraetime.net/auth/users`. Requires admin bearer. + tags: [auth] + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateUserRequest" + responses: + "200": + description: Created user + content: + application/json: + schema: + $ref: "#/components/schemas/AuthUserResponse" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: Caller-held VeraeTime JWT (never logged). + schemas: + Receipt: + type: object + description: Shared normalized receipt object across MCP and VeraeTime. + required: + - receipt_id + - hash + - scope + - created_at + - merkle + properties: + receipt_id: + type: string + description: Local id or VeraeTime certificate CID + hash: + type: string + description: SHA-256 hex (64 characters) + pattern: "^[0-9a-fA-F]{64}$" + scope: + type: string + description: local, shared, or global + enum: [local, shared, global] + cube_id: + type: string + description: Optional; local metadata + org_id: + type: string + description: Optional; local idempotency key; ignored by VeraeTime + created_at: + type: string + description: Timestamp when available + merkle: + type: string + description: Block hash / index when available + restamp_of: + type: string + description: Prior certificate when restamped + StampRequest: + type: object + required: [sha256] + additionalProperties: false + properties: + sha256: + type: string + description: > + SHA-256 digest (64 hex). Optional `sha256:` prefix is stripped by SDKs. + minLength: 64 + scope: + type: string + description: Default local. global → VeraeTime with restamp false. + enum: [local, shared, global] + default: local + cube_id: + type: string + org_id: + type: string + StampResponse: + type: object + required: [receipts] + properties: + receipts: + type: array + items: + $ref: "#/components/schemas/Receipt" + VerifyRequest: + type: object + required: [receipt_id] + additionalProperties: false + properties: + receipt_id: + type: string + want_scope: + type: string + description: Set to global to force VeraeTime verify. + enum: [local, shared, global] + VerifyResponse: + type: object + required: [valid, error, receipt] + properties: + valid: + type: boolean + error: + type: string + nullable: true + receipt: + nullable: true + allOf: + - $ref: "#/components/schemas/Receipt" + HashReportRequest: + type: object + required: [sha256] + additionalProperties: false + properties: + sha256: + type: string + description: SHA-256 digest (64 hex; optional sha256: prefix stripped) + minLength: 64 + org_id: + type: string + want_scope: + type: string + description: Set to global to force VeraeTime hash lookup. + enum: [local, shared, global] + HashReportResponse: + type: object + required: [receipts] + properties: + receipts: + type: array + items: + $ref: "#/components/schemas/Receipt" + SignupRequest: + type: object + required: [username, password] + additionalProperties: false + properties: + username: + type: string + password: + type: string + format: password + LoginRequest: + type: object + required: [username, password] + additionalProperties: false + properties: + username: + type: string + password: + type: string + format: password + AuthUserResponse: + type: object + required: [username, role] + properties: + id: + type: string + username: + type: string + role: + type: string + expires_at: + type: string + SessionResponse: + type: object + required: [valid] + properties: + valid: + type: boolean + username: + type: string + role: + type: string + expires_at: + type: string + CreateUserRequest: + type: object + required: [username, password, role] + additionalProperties: false + properties: + username: + type: string + password: + type: string + format: password + role: + type: string + enum: [user, admin] +tags: + - name: timestamping + description: Digests-only stamp, verify, and hash history + - name: auth + description: VeraeTime-direct account and session operations diff --git a/site/ways.html b/site/ways.html new file mode 100644 index 0000000..4190c43 --- /dev/null +++ b/site/ways.html @@ -0,0 +1,358 @@ + + + + + +Ways to use Verae timestamps + + + + + + + + +
+ Verae + +
+
+
+

Same MCP · many clients

+

Ways to use Verae timestamps

+

Hash locally; stamp digests only against the public Streamable HTTP endpoint. Start with AI MCP, then choose a browser, Mac/Windows UI, CLI, JS, or curl client. File bytes never upload.

+
+
+
+
+
+ + + + +
+

3 · UI · Windows

+

Windows GUI

+

Frozen amd64 EXEs — PySide6 GUI, CLI, optional hasher. SmartScreen warns (not code-signed); verify SHA-256 first.

+ +
+
+

4 · CLI

+

Command line

+

Official Python client: hash locally, stamp via MCP, write receipts under ~/.verae/receipts/. On Windows use verae-timestamp.exe.

+
uvx verae-mcp-timestamping-client \
+  --url https://mcp.verae.ai/mcp \
+  --scope global \
+  ./document.pdf
+ +
+
+

5 · JavaScript

+

Embed with fetch

+

Any web app: WASM/WebCrypto hash in-page, then POST Streamable HTTP JSON-RPC to /mcp (CORS *). Session id from Mcp-Session-Id.

+ +
+
+

6 · curl

+

Raw JSON-RPC

+

initialize → notifications/initialized → tools/call (stamp, verify, hash_report). Include Accept: application/json, text/event-stream.

+ +
+ +
+

Also

+

Local hasher · uvx server

+

Download verae-sha256 for your OS, or hash in-browser with WASM. Optional local MCP: uvx verae-mcp-timestamping-server and … setup for machine login.

+ +
+
+
+ +
+

Downloads hub

+

Stable artifact URLs on this host. macOS zip is Developer ID + notarized (not MAS).

+ +
+ +
+

macOS direct download (no TestFlight)

+

Universal Verae Timestamping.app (v0.2.1 / build 7), signed Developer ID Application: FlightLookup Inc. and Apple-notarized with staple. Gatekeeper accepts as Notarized Developer ID.

+
+
    +
  1. Download VeraeTimestamping-macos-universal.zip (~546 KiB).
  2. +
  3. Unzip → drag the app to /Applications (optional).
  4. +
  5. If Gatekeeper still blocks a quarantined copy: right-click → Open, or run xattr -dr com.apple.quarantine "/Applications/Verae Timestamping.app".
  6. +
  7. Open → first launch (MCP default https://mcp.verae.ai/mcp).
  8. +
+ +

CLI without the .app: uv sync then uv run verae-timestamp … in the client repo, or uvx verae-mcp-timestamping-client when published.

+
+
+ +
+

Request a macOS TestFlight invite

+

Optional App Store–style beta. Prefer the direct notarized zip if you do not want TestFlight. External testing still requires Apple Beta App Review — until that lands, invites are added manually for your Apple ID.

+
+

Public join link

+

When external Beta Review is approved, open:

+

https://testflight.apple.com/join/dsHsyx2Z

+

If the link says the beta is full or unavailable, request an invite below.

+ +
+
+

Request invite (Apple ID email)

+

Submit the Apple ID email you use for TestFlight. The server adds you to the external testers group via App Store Connect and resends the invitation.

+
+ + +
+ + Fallback: email marchon@gmail.com +
+
+

+

Enrollment can succeed while the build is still WAITING_FOR_BETA_REVIEW — you may not see the app in TestFlight until Apple approves the beta.

+
+
+
+
+ + + +