owlette docs
reference

firestore data model

this page maps the Firestore collections that owlette currently reads or writes, split by access path.

  • client/rules-visible paths are covered by firestore.rules and can be read or written by browser or agent Firebase clients when the rule allows it.
  • server-only Admin SDK paths are intentionally denied by rules, or fall through to the deny-all rule. Route handlers, Cloud Functions, and server workers use the Admin SDK for these paths.
  • legacy paths still exist for older dashboard, agent, or Cortex flows but are not the model new docs should teach first.
  • current public API paths are the storage models behind public API routes. API routes enforce auth and scope before touching Firestore.

client/rules-visible

These paths are explicitly matched in firestore.rules.

firestore/
|-- sites/{siteId}
|   |-- machines/{machineId}
|   |   |-- commands/pending
|   |   |-- commands/completed
|   |   |-- screenshots/{screenshotId}
|   |   |-- installed_software/{softwareId}
|   |   |-- hardware/{docId}
|   |   `-- metrics_history/{bucketId}
|   |-- deployments/{deploymentId}
|   |-- installer_templates/{templateId}
|   |-- project_templates/{templateId}
|   |-- project_distributions/{distributionId}
|   |-- roosts/{roostId}
|   |   |-- versions/{versionId}
|   |   `-- target_state/{machineId}
|   |-- webhooks/{webhookId}
|   |-- logs/{logId}
|   |-- audit_log/{entryId}
|   `-- settings/{settingId}
|-- config/{siteId}
|   |-- machines/{machineId}
|   |-- schedule_presets/{presetId}
|   |-- reboot_presets/{presetId}
|   `-- project_distribution_presets/{presetId}
|-- users/{userId}
|   |-- api_keys/{keyId}
|   |-- settings/{settingId}
|   `-- devicePrefs/{docId}
|-- installer_metadata/{document=**}
|-- system_presets/{presetId}
|-- api_keys/{keyHash}
|-- agent_tokens/{tokenId}
|-- agent_refresh_tokens/{tokenHash}
|-- device_codes/{phrase}
`-- chats/{chatId}
    `-- messages/{messageId}

sites/{siteId}

Top-level site document. Site reads require canAccessSite(siteId). Direct create, update, and delete are service-account only.

fieldtypenotes
namestringSite display name.
ownerstringUID of the user who created or owns the site.
createdAttimestampSite creation time.
timezonestringIANA timezone used by site-scoped scheduling surfaces.
tier / planstringPricing or quota tier, depending on caller generation.
roostEnabledbooleanSite-level roost kill switch. Missing or true means enabled.

sites/{siteId}/machines/{machineId}

Machine presence, status, metrics, process status, reboot state, live-view state, and capability flags live on the machine document itself. There are no current presence or status child documents.

Agents can read and write only their own machine document. Site members can read machine documents for sites they can access. Control-plane writes from the web go through API routes.

fieldtypenotes
machineIdstringHostname / machine identifier.
siteIdstringOwning site ID.
onlinebooleanAgent-reported online flag. The dashboard also checks heartbeat age.
lastHeartbeattimestampUpdated with each heartbeat/metrics write.
agent_versionstringAgent build version.
machine_timezonestringLegacy Windows timezone label.
machine_timezone_ianastringIANA timezone reported by newer agents.
cortexEnabledbooleanPer-machine Cortex delivery kill switch. Missing means enabled.
cortexStatusmapLocal Cortex status and heartbeat fields.
rebooting, shuttingDownbooleanCurrent machine power-operation flags.
rebootScheduledAt, shutdownScheduledAttimestamp/numberCountdown anchors used by the dashboard.
rebootPendingmap{ active, processName, reason, timestamp }.
rebootStatemapLast fired schedule entry plus current reboot attempt.
lastScreenshotmap/nullLatest screenshot pointer surfaced by live view.
liveViewmap{ active, interval, startedAt, expiresAt } when live view is running.
capabilitiesmapFeature gates such as displayRemoteApply.
metricsmapCurrent metrics payload described below.

Current metrics use schema version 2 and are nested on the machine document:

fieldtypenotes
metrics.schemaVersionnumberCurrent value is 2.
metrics.profileHashstring/nullMatches hardware/profile.signatureHash.
metrics.timestamptimestampMetrics write time.
metrics.cpusmapCPU metrics keyed by profile ID.
metrics.memorymapMemory percent and used GB.
metrics.disksmapDisk usage keyed by profile ID.
metrics.diskiomapPer-volume IO metrics.
metrics.gpusmapGPU metrics keyed by profile ID.
metrics.nicsmapNetwork interface throughput keyed by profile ID.
metrics.networkmapPing, packet loss, gateway, and network health fields.
metrics.primarymapCurrent primary CPU/disk/GPU/NIC IDs.
metrics.processesmapRuntime process status map from the agent.
metrics.displayDriftCountnumberCount of monitors that drift from assigned topology.

Legacy singular metrics.cpu, metrics.disk, and metrics.gpu are deleted by current agents after writing v2 metrics. The dashboard still shims older cached shapes during rollout windows.

sites/{siteId}/machines/{machineId}/commands/{commandDoc}

Command queues use two singleton documents:

  • commands/pending
  • commands/completed

Each document stores command IDs as top-level map fields. A pending document looks like this:

{
  "restart_DESKTOP01_1712000000000": {
    "type": "restart_process",
    "status": "pending",
    "createdAt": "<server timestamp>",
    "expiresAt": "<timestamp>",
    "auditCorrelationId": "optional",
    "process_name": "TouchDesigner"
  }
}

Completed, failed, cancelled, and in-progress states are written into commands/completed under the same command ID:

fieldtypenotes
statusstringcompleted, failed, cancelled, or an intermediate status such as downloading.
resultanyPresent for successful or cancelled terminal states.
errorstringPresent for failed terminal states.
completedAttimestampTerminal completion time.
updatedAttimestampProgress update time.
progressnumberOptional progress percentage.
deployment_idstringOptional deployment correlation.
typestringOriginal command type when supplied by the handler.

The server writes pending commands with writeCommandFanOut(). The agent listens to commands/pending, processes unseen map entries, writes the result to commands/completed, then deletes the command field from commands/pending.

sites/{siteId}/machines/{machineId}/hardware/{docId}

Hardware profile documents are readable by site members and writable by the agent for its own machine.

doc IDwriternotes
profileagentStatic CPU, disk, GPU, and NIC inventory.
displayagentLive display topology and assignment/drift data.
displayModesagentOn-demand display mode catalogue.

hardware/profile uses this shape:

fieldtypenotes
schemaVersionnumberHardware profile schema.
signatureHashstringStable hash used by metrics joins.
capturedAttimestampCapture time.
agentVersionstringAgent version that captured the profile.
cpus, disks, gpus, nicsarrayStatic device profile arrays.

sites/{siteId}/machines/{machineId}/screenshots/{screenshotId}

Screenshot history is written by server APIs after upload. Site members can read the history gallery.

fieldtypenotes
urlstringStorage URL for the image.
timestamptimestamp/numberCapture time.
sizeKBnumberImage size in KB.
storagePathstringBacking object path when present.

sites/{siteId}/machines/{machineId}/installed_software/{softwareId}

Agent-written software inventory from the Windows registry.

fieldtypenotes
name, version, publisherstringRegistry metadata.
install_locationstringInstallation directory.
uninstall_commandstringUninstall command from registry.
installer_typestringDetected installer family.
registry_keystringRegistry key reference.
detected_attimestampInventory write time.

sites/{siteId}/machines/{machineId}/metrics_history/{bucketId}

Daily metric history buckets, keyed by YYYY-MM-DD, are written by Cloud Functions from machine metric updates.

fieldtypenotes
samplesarrayTime-series samples.
meta.lastSampletimestampLast sample time.
meta.sampleCountnumberNumber of samples in the bucket.
meta.resolutionstringAggregation resolution.

sites/{siteId}/deployments/{deploymentId}

Installer deployment records. Site members can read them. Server APIs create, update, cancel, retry, uninstall, and delete them.

fieldtypenotes
namestringDeployment display name.
installer_name, installer_urlstringInstaller metadata.
silent_flagsstringOptional installer flags.
verify_pathstring/nullOptional post-install check path.
close_processesarrayProcesses to close before install.
parallel_installbooleanWhether targets can install in parallel.
targetsarray{ machineId, status, progress, error? } rows.
statusstringpending, in_progress, completed, failed, partial, cancelled, or uninstalled.
createdBy, createdAt, updatedAtstring/timestampAudit metadata.

Target status values include pending, closing_processes, downloading, installing, completed, failed, cancelled, and uninstalled.

sites/{siteId}/installer_templates/{templateId}

Site-scoped deployment templates managed through server APIs and dashboard actions.

fieldtypenotes
namestringTemplate display name.
installer_name, installer_urlstringInstaller source.
silent_flagsstringSuggested installer flags.
verify_pathstring/nullOptional verification path.
close_processesarrayProcess names to close before install.
timeout_secondsnumber/nullOptional install timeout.
createdAt, updatedAttimestampTimestamps.

sites/{siteId}/roosts/{roostId}

The v2 project distribution model. Site members can create roost shells and edit non-pointer metadata. Version pointer changes are server-mediated through API routes.

fieldtypenotes
schemaVersionnumberCurrent roost schema is 2.
namestringDisplay name.
targetsstring[]Target machine IDs.
extractPathstringDestination root on target machines.
versionCounternumberMonotonic per-roost version number counter.
currentVersionIdstring/nullCurrent immutable version ID.
currentVersionNumbernumber/nullDenormalized current version number.
currentVersionDescriptionstring/nullDenormalized current version description.
previousVersionIdstring/nullPrevious head before the last publish/rollback.
versionUrlstring/nullUnsigned R2 object URL for the current version body.
totalFiles, totalSizenumberCurrent version summary.
createdAt, createdBy, updatedAttimestamp/stringAudit metadata.

Direct Firestore create requires name, targets, createdAt, and schemaVersion: 2, and forbids client-supplied version pointer fields. Direct update cannot change pointer fields or schemaVersion.

sites/{siteId}/roosts/{roostId}/versions/{versionId}

Immutable version metadata. Version bodies live in R2, not in this document. Client-side create, update, and delete are denied by rules.

fieldtypenotes
versionIdstringContent-addressed SHA-256 of the canonical version body.
versionNumbernumberMonotonic, 1-indexed number within the roost.
descriptionstringPublish description.
versionUrlstringR2 object URL for the version body.
createdAt, createdBytimestamp/stringAuthor metadata.
totalSize, totalFilesnumberVersion summary.
parentVersionIdstring/nullHead version before this publish.

sites/{siteId}/roosts/{roostId}/target_state/{machineId}

Agent-reported per-target reality for roost sync. The agent for the specific machine can create or update its own document; site members can read or delete stale documents.

fieldtypenotes
reportedVersionIdstringVersion the agent is syncing or has committed.
statusstringpending, downloading, assembling, committed, failed, or cancelled.
updatedAttimestampLast report time.
errorstringTruncated error message on failure.
chunks_fetched, chunks_total, chunks_dedupnumberDownload progress counters.
files_total, files_assembled, files_skippednumberAssembly progress counters.

sites/{siteId}/logs/{logId}

Site-level event logs. This is the current dashboard log collection. It is not under each machine document.

fieldtypenotes
timestamptimestampEvent time.
actionstringEvent type, such as deployment or process action.
levelstringinfo, warning, or error.
machineId, machineNamestringSource machine.
processNamestringOptional process.
processIdstringOptional process id.
detailsmap/stringOptional details.
userIdstringOptional initiating user.
screenshotUrlstringOptional screenshot pointer.
eventTypestringOptional agent alert event type.
exePath, suggestedPathsstring/arrayPresent on exe_missing entries when the agent found missing executable context.

sites/{siteId}/audit_log/{entryId}

Security-boundary audit records. Site admins can read. Direct client writes are denied; server handlers write through audit helpers.

sites/{siteId}/webhooks/{webhookId}

Site-scoped webhook configuration. Site members can read. All writes go through server APIs.

fieldtypenotes
url, namestringDelivery endpoint and label.
eventsstring[]Subscribed webhook events.
enabledbooleanDelivery enabled flag.
secretstringHMAC secret stored server-side.
createdAt, createdBy, updatedAttimestamp/stringMetadata.
lastTriggered, lastStatus, failCounttimestamp/numberDelivery health fields.

Delivery history is stored under webhook subcollections by server APIs and is not directly covered by a client rules stanza.

sites/{siteId}/settings/{settingId}

Site settings such as shared LLM/Cortex configuration. Site members can read; server APIs write.

Known document IDs include:

  • llm
  • cortex

config/{siteId}/machines/{machineId}

Process configuration and machine-level persistent settings. Agents can read and write their own config; server APIs also write config changes.

fieldtypenotes
versionstringConfig schema version.
processesarrayProcess config objects.
rebootSchedulemapOffline-capable scheduled reboot config.
displaysmapDisplay assignment and auto-restore settings.
environment, sentry, watchdogmapUser-editable top-level config sections.

Current process config uses id/processId, name, exe_path, file_path, cwd, priority, visibility, time_delay, time_to_init, relaunch_attempts, launch_mode, derived autolaunch, schedules, and optional schedulePresetId.

config preset collections

pathpurposedirect access
config/{siteId}/schedule_presets/{presetId}Process schedule presets.Site members read; server writes.
config/{siteId}/reboot_presets/{presetId}Reboot schedule presets.Site members read; server writes.
config/{siteId}/project_distribution_presets/{presetId}Legacy distribution presets.Site members read; server writes.

users/{userId}

User profile and access metadata. Users can read their own document; superadmins can read every user. Users can self-create only as member. Server APIs manage roles, site assignments, and deletion.

fieldtypenotes
emailstringUser email.
displayNamestringOptional display name.
rolestringmember, admin, or superadmin.
sitesstring[]Site IDs assigned to members/admins.
createdAttimestampCreation time.
mfaEnrolled, mfaSecret, backupCodesboolean/string/arrayMFA state.
passkeyEnrolledbooleanWhether passkeys exist.

user subcollections

pathpurposedirect access
users/{userId}/api_keys/{keyId}User-visible API key inventory metadata.User can read own keys; direct writes denied.
users/{userId}/settings/{settingId}User preferences and encrypted LLM settings.User can read/write own settings.
users/{userId}/devicePrefs/{docId}Per-device UI preferences.User can read/write own device preferences.

The raw API key hash lookup lives at top-level api_keys/{keyHash} and is server-only.

installer_metadata/{document=**}

Publicly readable installer metadata. Server APIs write latest and version records.

Common documents:

  • installer_metadata/latest
  • installer_metadata/data/versions/{version}

system_presets/{presetId}

Platform-level deployment preset library. Authenticated users can read. Server APIs create, update, and delete.

fieldtypenotes
name, software_name, category, descriptionstringDisplay metadata.
installer_name, installer_urlstringInstaller source.
silent_flagsstringSuggested silent flags.
verify_pathstring/nullOptional install verification path.
close_processesstring[]Processes to close before installing.
timeout_secondsnumber/nullOptional timeout.
ordernumberSort order.
createdAt, updatedAttimestampTimestamps.

server-only Admin SDK

These collections are written or read through server routes, Cloud Functions, or server workers. Direct browser and agent access is denied by explicit rules or by the catch-all deny rule.

pathpurpose
api_keys/{keyHash}Fast API-key lookup table with key hash, user, key ID, scopes, expiry, and revocation metadata.
agent_tokens/{tokenId}Legacy agent registration token state.
agent_refresh_tokens/{tokenHash}Hashed agent refresh tokens with site and machine binding.
device_codes/{phrase}10-minute device-code pairing phrase state. Deleted after agent poll/consume or expiry.
mfa_pending/{userId}Temporary MFA setup secret and expiry.
webauthn_challenges/{challengeId}Single-use passkey registration/authentication challenge.
users/{userId}/passkeys/{credentialId}Passkey credentials and metadata, managed by passkey APIs.
installer_uploads/{uploadId}Temporary installer upload sessions.
bug_reports/{reportId}User/agent feedback and bug submissions.
global/security_configPlatform security kill-switch config.
global/audit_log/entries/{entryId}Platform audit records for non-site-scoped actions.
siteChunks/{digest}Emulator/test chunk-presence rows used when R2 is not available.

siteChunks/{digest}

Production chunk bytes live in Cloudflare R2. In emulator/E2E mode, hasChunk() checks this top-level collection instead.

fieldtypenotes
siteIdstringSite that owns the seeded chunk.
hashstringBare 64-hex SHA-256 digest.
sizenumberSeeded size in bytes.
createdAttimestampSeed time.

legacy

These paths may still be present during migration windows. New integrations should use the current public API storage models and routes instead.

sites/{siteId}/project_distributions/{distributionId}

Legacy project distribution records. They coexist with roost v2 during the cutover but are not the current project sync model.

fieldtypenotes
namestringDistribution name.
project_name, project_urlstringLegacy package metadata.
extract_pathstringDestination path.
targetsarrayPer-machine target rows.
statusstringpending, in_progress, completed, failed, partial, or cancelled.
createdAt, createdBy, updatedAttimestamp/stringMetadata.

sites/{siteId}/project_templates/{templateId}

Legacy reusable project distribution templates. Current roost upload/publish flows do not depend on this path.

config/{siteId}/project_distribution_presets/{presetId}

Legacy distribution preset library. It remains rules-visible for older UI flows and built-in preset overrides.

chats/{chatId} and chats/{chatId}/messages/{messageId}

Legacy Cortex conversation storage. Rules still expose this collection to the owning user, and older Cortex categorization paths still read/write it.

fieldtypenotes
userIdstringConversation owner.
siteIdstringSite context.
targetTypestringmachine or site.
targetMachineId, machineNamestring/nullTarget context.
title, categorystringConversation label and LLM category.
sourcestringuser or autonomous.
eventId, autonomousSummarystring/nullAutonomous event linkage.
createdAt, updatedAttimestampTimestamps.

Messages under messages/{messageId} contain role, content, and createdAt.

legacy/local Cortex bridge paths

Older local Cortex bridge code references these paths:

  • sites/{siteId}/machines/{machineId}/cortex/active-chat
  • sites/{siteId}/cortex-events/{eventId}
  • sites/{siteId}/cortex-state/lock

They are not the current public chat API storage model. Treat them as legacy dashboard/agent internals unless the owning Cortex code is explicitly being updated.

machine-level log shipping

The older log-shipping helper attempts to write sites/{siteId}/machines/{machineId}/logs/{logId}. Current rules do not define that subcollection, and current dashboard activity logs use sites/{siteId}/logs/{logId}.

current public API

These storage models sit behind public API routes. Clients should call the API surface rather than reading or writing these collections directly.

public chat storage

Current public Cortex chat APIs use chat_conversations/{conversationId}. The most recent messages are embedded on the conversation document; older messages spill to chat_conversations/{conversationId}/chat_messages/{messageId} after the embedded array reaches 200 entries.

fieldtypenotes
conversationIdstringconv_ plus random URL-safe ID.
titlestringNormalized title, max 100 chars.
siteIdstringSite context.
machineIdstringOptional target machine.
ownerUidstringConversation owner.
createdAt, updatedAttimestampTimestamps.
deletedAttimestampSoft-delete marker when present.
messagesarrayEmbedded most-recent messages.
messageCountnumberLifetime message count, including spilled rows.

Embedded and spilled message rows contain:

fieldtypenotes
rolestringuser, assistant, or system.
contentstringMessage text.
timestamptimestampMessage write time.
spilledAttimestampPresent only on spilled rows.

roost quota and usage

Quota and usage storage is server-managed. Public routes such as GET /api/sites/{siteId}/quota and GET /api/sites/{siteId}/quota/history expose scoped views.

pathwriter/readerpurpose
sites/{siteId}/roost/quotaCloud Functions and quota APICurrent storage tier, used bytes, plan limit, alarm state, and reconciliation time.
sites/{siteId}/roost/quota/pending/{reservationId}quota pre-upload checkTemporary pending byte reservations.
sites/{siteId}/quota_alarms/{alarmId}quota reconcilerAlarm threshold crossings with threshold and firedAt.
sites/{siteId}/usage_events/{eventId}telemetry functionRaw usage events: class_a_op, class_b_op, egress, or storage_snapshot.
sites/{siteId}/usage_summaries/{yyyyMm}telemetry aggregatorMonth-to-date counters and cost rollups.

roost version bodies and chunk bytes

Firestore stores roost metadata and pointers only. Actual version bodies and chunk bytes live in R2:

objectstoragekey shape
chunksR2 content bucketproject-content/{siteId}/{firstTwoHex}/{digest}
version bodiesR2 manifests bucketproject-manifests/{siteId}/{roostId}/{versionId}.json

The Firestore roosts/{roostId}/versions/{versionId} document records metadata and the R2 URL; it does not contain the full version body.

on this page