Your catalog, your bidders, your invoices, your audit log — all live in their own InvariantDB graph. There is no shared table. There is no cross-tenant access path, even with a compromised credential.
Every Hammerwerks tenant gets a dedicated graph in InvariantDB named auction_<auctioneerId>. All catalog data, bidder records, invoices, seller statements, audit events, and API keys live in that graph. There is no shared schema. Queries are scoped at the auth-middleware layer; no route can return data from a different tenant's graph.
The architectural consequence: data leakage between auction houses is structurally prevented rather than policy-enforced. Even a SQL-injection-style attack on one tenant cannot reach into another tenant's data — there is no edge that could carry the request across graphs.
API keys for the MCP server (and future REST API) follow a defensive format:
hw_<auctioneerId>_<32-hex-secret>The auctioneer ID is encoded so we know which graph to authenticate against. The 32-character secret is sha256-hashed before storage; the plaintext is shown exactly once at creation and never persisted in our database. If a key is lost, revoke + create a new one.
Revocation sets revoked: true rather than deleting the key node — this preserves the audit trail of actions taken under that key. Past :AuditEvent nodes that reference the apiKeyId still resolve, so you can see exactly what happened under any historical credential.
Every admin action and every MCP write tool emits a :AuditEvent node in your tenant graph. The shape:
{
eventId: '…',
action: 'lot.approve' | 'invoice.refund' | 'mcp.create_auction' | …,
actorSub: 'cognito:<sub>' | 'mcp:<apiKeyId>',
actorRole: 'owner' | 'admin' | 'cataloger' | 'accountant' | 'viewer',
target: {…}, // lot/auction/invoice id, etc.
meta: {…}, // before/after, apiKeyName, etc.
at: datetime()
}Query via GET /api/audit with optional actionPrefix filter. State-licensed auctioneers in jurisdictions that require an immutable activity log get one out of the box.
| Layer | Implementation |
|---|---|
| Compute | AWS Lambda (no EC2). Auto-scaling, no patched instances to maintain. |
| Database | InvariantDB — bitemporal graph, hash-chained immutable audit trail, WORM-mode capable. |
| Photos | S3 with per-tenant prefix scoping. Presigned URLs for upload/download. |
| Realtime | API Gateway WebSocket. Bidder connections isolated per tenant. |
| CDN | CloudFront in front of the public catalog (StaticOwl-rendered HTML). |
| Payments | Stripe Connect (per-tenant accounts). PCI scope: SAQ A only (we don't touch raw card numbers). |
| AWS SES with per-tenant From-name + DKIM. SPF and DMARC monitored. | |
| Backups | Daily snapshots of each tenant graph. Restore-on-request supported. |
Detailed security questionnaire available on request. Most B2B vendor reviews complete in 1-2 weeks.
Request the security overview →