Security

Per-tenant by construction.

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.

Tenant isolation.

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 & authentication.

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.

Audit log on every action.

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.

Hosting & infrastructure.

LayerImplementation
ComputeAWS Lambda (no EC2). Auto-scaling, no patched instances to maintain.
DatabaseInvariantDB — bitemporal graph, hash-chained immutable audit trail, WORM-mode capable.
PhotosS3 with per-tenant prefix scoping. Presigned URLs for upload/download.
RealtimeAPI Gateway WebSocket. Bidder connections isolated per tenant.
CDNCloudFront in front of the public catalog (StaticOwl-rendered HTML).
PaymentsStripe Connect (per-tenant accounts). PCI scope: SAQ A only (we don't touch raw card numbers).
EmailAWS SES with per-tenant From-name + DKIM. SPF and DMARC monitored.
BackupsDaily snapshots of each tenant graph. Restore-on-request supported.

Compliance & certifications.

Detailed security questionnaire available on request. Most B2B vendor reviews complete in 1-2 weeks.

Request the security overview →