Global administration and SaaS provisioning
QilbeeDB separates installation administration from company data access. A locally provisioned master owns global administrative authority. A SaaS backend can receive a narrower global credential to register companies. Each company then uses its own tenant credentials and exact resource grants.
This contract is available in 0.11.0. There is no default master password, anonymous registration endpoint, or HTTP operation that creates the first master.
Choose an authority#
| Principal | Credential | Authority |
|---|---|---|
| Installation master | qdbg1_…, is_master: true |
All four global administrative capabilities; delegates service keys and appoints administrators in any tenant |
| Signup backend | qdbg1_…, tenant_create only |
Creates a new tenant and its first administrator; cannot take over an existing tenant or administer global credentials |
| Administrative service | qdbg1_…, explicit subset |
Performs only the selected global operations |
| Company administrator | qdb1_… |
Issues credentials and manages policy inside its own tenant |
| Application or agent | qdb1_… |
Uses explicitly granted capabilities and exact project, mission, agent and visibility scopes |
Global keys and tenant keys have separate persisted records, verifier domains and authentication paths. A tenant cannot gain global authority by choosing a tenant name, subject, capability string, grant or request field. Global keys do not authenticate memory, search, learning or tenant credential endpoints.
The master has administrative control over every company: it can explicitly appoint a tenant administrator, which can issue that company's application credentials. This is powerful access and must be protected accordingly. The appointment records the global actor in the new administrator's history; there is no silent switch of a request's tenant or automatic wildcard memory grant.
Bootstrap the master once#
Stop the server and use exclusive access to its persistent data directory:
umask 077
(set -C; qilbeedb bootstrap-master /var/lib/qilbeedb/data master \
> /secure/operator/master.json)
The command returns contract_version, credential and the one-time secret.
Store the result in a secret manager. Only a verifier is persisted in QilbeeDB;
the command's output must not enter application logs, Git, images or user data.
The command fails if this installation has ever bootstrapped a master, including
when that master was subsequently revoked. Starting an empty server alone does
not provision any authority.
Host administrators who can stop QilbeeDB and write its database files are trusted operators. Protect host access, backups, container administration and secret manager permissions as part of the same security boundary.
Delegate the SaaS registration service#
The master issues a backend key through POST /api/v1/admin/credentials:
{
"contract_version": 1,
"spec": {
"subject_id": "saas-signup-service",
"capabilities": ["tenant_create"],
"expires_at_millis": null
}
}
Set an explicit future expiration for a time-limited service key. A global issuer
needs global_credential_admin, may delegate only capabilities it already has,
and cannot issue a credential whose expiry exceeds its own. Issued service keys
always have is_master: false; the payload cannot change that flag.
The response is HTTP 201 with sanitized credential metadata and the new
secret. Deliver the key only to the signup backend's secret store. Rotation,
issuance and initial administrator delivery return secrets once and are not
idempotent secret-delivery protocols. Persist the returned IDs and metadata.
The public signup flow should work as follows:
- The browser authenticates to the SaaS backend using the SaaS application's identity provider. No global QilbeeDB key is sent to the browser.
- The backend verifies the account, applies its registration policy and abuse limits, and generates an immutable company ID. It associates that ID with the verified account on the server; it does not trust an arbitrary tenant ID from browser storage or a query parameter as proof of membership.
- The backend registers the company using its restricted global key.
- It stores the returned tenant administrator key securely and uses it to issue appropriately scoped application credentials. It does not expose that administrator key as an ordinary user session.
- Requests from agents and users use company-specific credentials. QilbeeDB checks tenant, capability, scope, subject and current credential state.
QilbeeDB supplies database authorization and optional
provisioned administrator login. Email verification,
billing, invitation acceptance, public signup limits and application account recovery for the
SaaS application belong to the application layer. Possession of a
tenant_create key allows tenant creation, so it must never be distributed as a
public client API key.
Register a company#
Call POST /api/v1/admin/tenants with Authorization: Bearer <global-key>:
{
"contract_version": 1,
"tenant_id": "company-6cb1eb2b",
"subject_id": "initial-company-operator"
}
The server requires tenant_create. It atomically writes the tenant marker,
registration provenance and first tenant administrator credential while checking
the authorizing global credential's exact stored revision. The administrator
receives credential_admin and policy_admin, with no memory grants.
HTTP 201 contains tenant, credential and the one-time tenant secret.
tenant.created_by identifies the global actor; initial_admin_id identifies the
new administrator. Tenant and subject IDs contain 1–256 UTF-8 bytes, must not be
blank, and must not contain control characters. IDs are exact, case-sensitive
identities; they are not normalized company display names.
An existing tenant ID returns 409 revision_conflict and never replaces its
authority. Concurrent requests for the same new ID have only one winner. This
also protects companies created earlier through bootstrap-tenant.
If the response is lost, do not claim the tenant was not created and do not retry
with a different company ID automatically. A credential with tenant_inspect
can inspect the registration; an operator with tenant_admin can appoint a new
administrator when secret delivery is uncertain. The registration-only service
cannot perform that recovery. Revoke an unaccounted-for initial administrator
through the tenant credential API after recovering access.
Administrative API#
All routes require a global bearer key, use contract_version: 1, and return
Cache-Control: no-store. The request body limit is 65,536 bytes.
| Method and path | Required authority | Result |
|---|---|---|
GET /api/v1/admin/identity |
Any active global credential | Current credential metadata |
POST /api/v1/admin/credentials |
global_credential_admin, subset and expiry checks |
New delegated global credential and one-time secret |
GET /api/v1/admin/credentials/{id} |
global_credential_admin, capability superset of target |
Credential metadata and history |
POST /api/v1/admin/credentials/{id}/rotate |
Self, or authorized global credential administrator | New secret at the expected revision |
POST /api/v1/admin/credentials/{id}/revoke |
Self, or authorized global credential administrator | Revoked credential metadata |
POST /api/v1/admin/tenants |
tenant_create |
New company and first administrator |
GET /api/v1/admin/tenants/{tenant} |
tenant_inspect |
Tenant ID and registration provenance |
POST /api/v1/admin/tenants/{tenant}/admin-credentials |
tenant_admin |
Additional administrator for that exact existing tenant |
Rotation and revocation use
{"contract_version":1,"expected_revision":1}. Delegated administrators cannot
rotate or revoke the bootstrap master, even if they hold all global capabilities.
A key can rotate or revoke itself. Rotation preserves permissions and expiry.
Each change appends actor, action, revision and timestamp to the target history.
Old and revoked secrets stop authenticating durably, including after restart.
Administrator appointment uses
{"contract_version":1,"subject_id":"replacement-operator"}. It does not
automatically revoke existing tenant keys. Inspection returns registration:
null for locally bootstrapped tenants, whose original registration provenance
must not be fabricated.
These capabilities are independent: tenant_create does not imply
tenant_inspect, tenant_admin, or global_credential_admin. Revoking an issuer
does not cascade to previously issued keys or delete companies. Revoke affected
credentials explicitly using their recorded IDs. This release does not expose a
tenant listing, company suspension, billing API or human login interface.
Errors and recovery#
| Status | Meaning |
|---|---|
| 400 | Invalid JSON, unknown fields, unsupported version or invalid identity/expiry |
| 401 | Missing, malformed, expired, rotated or revoked credential |
| 403 | A valid tenant key used for global administration, or a global key without required authority |
404 tenant_not_found |
Authorized lookup or administrator appointment for an absent tenant |
409 revision_conflict |
Existing tenant, stale expected revision or concurrent authority change |
| 413 | Body exceeds the transport limit |
| 500 | Internal failure or stored authority inconsistency; fail closed |
If the master key is lost or revoked, a trusted host operator can stop the server
and run qilbeedb recover-master <data-directory> <expected-revision>. This
rotates only the existing bootstrap master, preserves its ID and history, and
records recovered_by_local_operator. A stale revision fails. Secure the new
one-time output before restarting the service. There is no network recovery
endpoint and recovery does not revive revoked delegated keys.
Validation and security basis#
The feature's tests exercise separate global and tenant authentication, denied privilege escalation, restricted signup keys, cross-company memory isolation, concurrent registration, expiry, rotation, revocation after reopening storage, offline recovery and corrupt authority records. A real loopback HTTP test checks responses against the OpenAPI document served by the same process.
The design follows least privilege, default denial and authorization on every request as described in the OWASP Authorization Cheat Sheet. For AWS deployments, use the access control and rotation guidance in AWS Secrets Manager best practices. These implementation tests are not an external penetration test or a compliance certification.