Firestore Data Model¶
Complete schema for all Firestore collections and documents.
Collection Hierarchy¶
firestore/
├── sites/{siteId}/
│ ├── machines/{machineId}/
│ │ ├── presence (single document)
│ │ ├── status (single document)
│ │ └── commands/
│ │ ├── pending/{cmdId}
│ │ └── completed/{cmdId}
│ ├── deployments/{deployId}
│ ├── project_distributions/{distId}
│ ├── installer_templates/{tplId}
│ ├── project_templates/{tplId}
│ ├── activity_logs/{logId}
│ ├── webhooks/{webhookId} (webhook notification configs)
│ ├── settings/
│ │ ├── llm (single document)
│ │ └── cortex (single document, autonomous config)
│ ├── cortex-events/{eventId} (autonomous investigation records)
│ └── cortex-state/
│ └── lock (single document, concurrency control)
│
├── config/{siteId}/
│ └── machines/{machineId} (single document)
│
├── users/{userId}
│ ├── passkeys/{credentialId} (WebAuthn credentials)
│ └── settings/
│ ├── llm
│ └── preferences
│
├── chats/{chatId} (Cortex conversations)
├── agent_tokens/{registrationCode}
├── agent_refresh_tokens/{tokenHash}
├── mfa_pending/{userId}
├── webauthn_challenges/{challengeId}
└── installer_metadata/
├── latest (single document)
└── data/versions/{version}
sites/{siteId}¶
Top-level site document.
| Field | Type | Description |
|---|---|---|
name |
string | Display name (e.g., "NYC Office") |
owner |
string | UID of the user who created the site |
createdAt |
timestamp | When the site was created |
sites/{siteId}/machines/{machineId}/presence¶
Agent heartbeat — updated every 30 seconds.
| Field | Type | Description |
|---|---|---|
online |
boolean | Whether the machine is connected |
lastHeartbeat |
timestamp | Last heartbeat time (server timestamp) |
agent_version |
string | Agent version (e.g., "2.1.8") |
os |
string | OS description (e.g., "Windows 11 Pro 10.0.22631") |
sites/{siteId}/machines/{machineId}/status¶
System metrics — updated every 60 seconds.
| Field | Type | Description |
|---|---|---|
cpu |
number | CPU usage percentage (0-100) |
memory |
number | RAM usage percentage (0-100) |
disk |
number | Primary disk usage percentage (0-100) |
gpu |
number | GPU usage percentage (0-100) |
cpu_model |
string | CPU model name |
processes |
map | Per-process status map (see below) |
online |
boolean | Redundant online flag (for atomic updates) |
lastHeartbeat |
timestamp | Redundant heartbeat (for atomic updates) |
processes map¶
sites/{siteId}/machines/{machineId}/commands/pending/{commandId}¶
Pending command from dashboard.
| Field | Type | Description |
|---|---|---|
type |
string | Command type (see Agent Commands) |
timestamp |
number | Unix timestamp (milliseconds) |
status |
string | Always "pending" |
| ...additional fields | varies | Command-specific data (e.g., process_name, installer_url) |
sites/{siteId}/machines/{machineId}/commands/completed/{commandId}¶
Completed command result.
| Field | Type | Description |
|---|---|---|
type |
string | Original command type |
result |
string | Result message or error |
status |
string | "completed" or "failed" |
completedAt |
timestamp | When the command finished |
config/{siteId}/machines/{machineId}¶
Process configuration synced between agent and dashboard.
| Field | Type | Description |
|---|---|---|
version |
string | Config schema version |
processes |
array | Array of process objects |
Process object¶
{
"name": "TouchDesigner",
"exe_path": "C:\\Program Files\\...",
"file_path": "",
"command_line_args": "",
"autolaunch": true,
"priority": "Normal",
"visibility": "Normal",
"launch_delay": 0,
"init_time": 10,
"relaunch_attempts": 5
}
users/{userId}¶
User account document.
| Field | Type | Description |
|---|---|---|
email |
string | User's email address |
displayName |
string | Full name (optional) |
role |
string | "user" or "admin" |
sites |
array[string] | Assigned site IDs |
createdAt |
timestamp | Registration date |
mfaEnabled |
boolean | Whether 2FA is active |
mfaSecret |
string | Encrypted TOTP secret (if MFA enabled) |
mfaBackupCodes |
array[string] | Hashed backup codes |
passkeyEnrolled |
boolean | Whether user has registered passkeys |
users/{userId}/passkeys/{credentialId}¶
WebAuthn credential for passkey authentication.
| Field | Type | Description |
|---|---|---|
credentialPublicKey |
string | Base64URL-encoded public key |
counter |
number | Signature counter (for clone detection) |
transports |
array[string] | ["internal", "usb", "ble", "nfc"] |
deviceType |
string | "singleDevice" or "multiDevice" |
backedUp |
boolean | Whether credential is synced (e.g., iCloud Keychain) |
friendlyName |
string | User-assigned label (e.g., "MacBook Pro") |
createdAt |
timestamp | Registration date |
lastUsedAt |
timestamp | Last authentication date |
users/{userId}/settings/preferences¶
| Field | Type | Description |
|---|---|---|
temperatureUnit |
string | "celsius" or "fahrenheit" |
healthAlerts |
boolean | Receive machine offline emails |
processAlerts |
boolean | Receive process crash emails |
users/{userId}/settings/llm¶
| Field | Type | Description |
|---|---|---|
provider |
string | "anthropic" or "openai" |
encryptedApiKey |
string | AES-encrypted API key |
model |
string | Model ID (optional) |
updatedAt |
timestamp | Last update time |
agent_tokens/{registrationCode}¶
One-time registration code for agent OAuth.
| Field | Type | Description |
|---|---|---|
siteId |
string | Target site |
createdBy |
string | UID of admin who created it |
createdAt |
timestamp | Creation time |
expiresAt |
timestamp | Expiry (24 hours after creation) |
used |
boolean | Whether the code has been exchanged |
status |
string | "pending" |
Server-only
This collection is not accessible from any client (web or agent). Only the Admin SDK can read/write.
agent_refresh_tokens/{tokenHash}¶
Hashed refresh tokens for agent authentication.
| Field | Type | Description |
|---|---|---|
siteId |
string | Agent's site |
machineId |
string | Agent's machine hostname |
agentUid |
string | Firebase UID assigned to agent |
version |
string | Agent version when token was created |
createdAt |
timestamp | Token creation time |
lastUsed |
timestamp | Last refresh time |
Server-only
This collection is not accessible from any client. Only the Admin SDK can read/write.
mfa_pending/{userId}¶
Temporary MFA setup state.
| Field | Type | Description |
|---|---|---|
secret |
string | TOTP secret (plaintext, temporary) |
email |
string | User's email |
createdAt |
timestamp | When setup was initiated |
expiresAt |
timestamp | Expiry (10 minutes) |
webauthn_challenges/{challengeId}¶
Temporary WebAuthn challenge for passkey registration or authentication.
| Field | Type | Description |
|---|---|---|
challenge |
string | Base64URL-encoded challenge |
userId |
string|null | User ID (null for authentication, userId for registration) |
type |
string | "registration" or "authentication" |
createdAt |
timestamp | When challenge was generated |
expiresAt |
timestamp | Expiry (10 minutes) |
Single-use
Challenges are deleted immediately after verification. Expired challenges are also rejected.
installer_metadata/latest¶
Current latest installer version.
| Field | Type | Description |
|---|---|---|
version |
string | Version number (e.g., "2.1.8") |
download_url |
string | Firebase Storage download URL |
file_size |
number | File size in bytes |
release_date |
timestamp | Upload date |
checksum_sha256 |
string | SHA-256 hash of the installer |
release_notes |
string | Change description (optional) |
uploaded_by |
string | Admin UID |
sites/{siteId}/deployments/{deploymentId}¶
Software deployment record.
| Field | Type | Description |
|---|---|---|
name |
string | Deployment name |
installer_name |
string | Filename |
installer_url |
string | Download URL |
silent_flags |
string | Installation flags |
verify_path |
string | Post-install verification path |
targets |
array | [{machineId, status, progress}] |
status |
string | pending, in_progress, completed, failed |
createdBy |
string | UID |
createdAt |
timestamp | Creation time |
sites/{siteId}/project_distributions/{distributionId}¶
Project file distribution record.
| Field | Type | Description |
|---|---|---|
name |
string | Distribution name |
project_name |
string | ZIP filename (from URL) |
project_url |
string | Download URL |
extract_path |
string | Target extraction path |
verify_files |
array[string] | Files to verify after extraction |
targets |
array | [{machineId, status, progress}] |
status |
string | pending, in_progress, completed, failed, partial |
createdAt |
timestamp | Creation time |
sites/{siteId}/activity_logs/{logId}¶
Event log entries.
| Field | Type | Description |
|---|---|---|
timestamp |
timestamp | Event time |
action |
string | Event type (e.g., process_crashed) |
level |
string | info, warning, error |
machineId |
string | Source machine (optional) |
processName |
string | Related process (optional) |
details |
map | Additional context |
sites/{siteId}/webhooks/{webhookId}¶
Webhook notification configurations.
| Field | Type | Description |
|---|---|---|
url |
string | Webhook delivery URL (must be HTTPS) |
name |
string | Display name |
events |
array[string] | Subscribed events: process.crashed, machine.offline, etc. |
enabled |
boolean | Whether the webhook is active |
secret |
string | HMAC-SHA256 signing secret (hex-encoded) |
createdAt |
timestamp | Creation time |
createdBy |
string | Admin UID who created it |
lastTriggered |
timestamp|null | Last delivery attempt |
lastStatus |
number | Last HTTP response status (0 if never fired) |
failCount |
number | Consecutive delivery failures (auto-disables at 10) |
sites/{siteId}/settings/cortex¶
Autonomous Cortex configuration. Created per-site, disabled by default.
| Field | Type | Description |
|---|---|---|
autonomousEnabled |
boolean | Whether autonomous mode is active |
directive |
string | Custom directive text (empty = use default) |
maxTier |
number | Max tool tier (1=read-only, 2=+process mgmt, 3=+shell) |
autonomousModel |
string|null | Override LLM model for autonomous mode |
maxEventsPerHour |
number | Incoming event throttle per site |
cooldownMinutes |
number | Per machine+process cooldown between investigations |
escalationEmail |
boolean | Email admins when Cortex escalates |
updatedAt |
timestamp | Last update |
sites/{siteId}/cortex-events/{eventId}¶
Autonomous investigation records — one per triggered event.
| Field | Type | Description |
|---|---|---|
machineId |
string | Machine that triggered the event |
machineName |
string | Machine display name |
processName |
string | Process involved |
eventType |
string | process_crash or process_start_failed |
errorMessage |
string | Error details from agent |
timestamp |
timestamp | When the event was received |
chatId |
string | Links to chats/{chatId} |
status |
string | investigating, resolved, escalated, failed |
summary |
string | One-line outcome summary |
actions |
array | Tool calls made: [{tool, params, timestamp}] |
resolvedAt |
timestamp | When investigation completed |
durationMs |
number | Total investigation time |
sites/{siteId}/cortex-state/lock¶
Concurrency control for autonomous sessions.
| Field | Type | Description |
|---|---|---|
activeSessions |
number | Currently running autonomous investigations |
lastUpdated |
timestamp | Last lock update |
chats/{chatId}¶
Cortex conversation records (both user-initiated and autonomous).
| Field | Type | Description |
|---|---|---|
userId |
string | User who created the chat (absent for autonomous) |
siteId |
string | Site context |
targetType |
string | machine or site |
targetMachineId |
string|null | Target machine ID |
machineName |
string|null | Machine display name |
title |
string | Conversation title (first message, truncated to 100 chars) |
source |
string | user or autonomous |
eventId |
string|null | Links to cortex-events/{eventId} (autonomous only) |
autonomousSummary |
string|null | Quick outcome summary (autonomous only) |
createdAt |
timestamp | When the chat started |
updatedAt |
timestamp | Last activity |