Built so the server decides.
Bean's interface never grants access on its own. Organisation, ownership, actor and timestamps come from the server, and every request is checked again there.
Foundations
Tenant isolation
Data belongs to an organisation. Another organisation's records look like records that don't exist, and suspended organisations can't be written to.
tenant_idTwo kinds of authority
Organisation roles (owner, admin, member) decide whose data you may touch and who manages membership. Account permissions such as INVENTORY_CREATE decide what you may do in each module.
403 ≠ 401Sessions
An HTTP-only session cookie with a one-hour rolling idle timeout and a six-hour absolute lifetime. Unsafe requests must come from an allowed origin. No tokens are stored in the browser.
bean.sidAudit
Audited writes record actor, action, resource and organisation. The audit table is append-only at the database level.
audit_logsHealth
Separate liveness and readiness endpoints, both public, uncached and free of internal detail, for load balancers and monitoring.
/health/ready
A documented path from someone else's app into your stock.
Register
An owner or administrator registers the app. Bean returns its app key and secret once and stores only a bcrypt hash of the secret.
Subscribe and activate
Choose the event types it may send. Activation succeeds only when the organisation is active, a credential exists and a supported subscription is enabled.
Deliver
The app posts server-to-server with its key and secret. Each event is checked against its registered JSON Schema and queued; a repeated event ID is acknowledged, not applied twice.
Process
A worker applies the business effect, such as deducting stock and recording the sale, in the same transaction as its audit entry. Failures roll back and are retried.
Observe
The application's page shows its timeline, audit history and 30-day analytics: processed and failed events, duplicates, and processing time.
Supported events today: transaction.completed and inventory.adjusted. Refund and referral events are proposed contracts, not enabled. There are no ready-made connectors for specific POS or store brands: the sending system calls this API.
What it runs on
Backend
Express 5 API on Node.js with PostgreSQL, including the session store. Schema changes go through a migration runner that tracks applied versions and refuses on drift.
PostgreSQLFrontend
A React application with cookie-based sessions, self-hosted fonts and no third-party requests.
ReactContract
The API reference and Postman collection are generated from one specification, and the test suite fails if a route is undocumented.
API spec
This website is separate from the Bean application. It has no access to the application or its data.