C
Cyrano Security
12 min read
security for property, as a data model

Security for property means property_id is the primary key, not camera_id. Every alert, every report, every export is scoped to one building.

The top SERP for security for property sells camera kits, sensor kits, and guard hours. The property is treated as a shipping address and a billing row. On a Cyrano deployment, the property is the primary schema entity. One unit per property, one provisioning file, one on-call rotation, one monthly PDF. This page is about the field in that file (property_label), where it gets written, and the four downstream systems that read it.

See the property-scoped console
4.9from 50+ properties
One Cyrano unit per property, one provisioning file, one property_label
Alerts route per property, not per camera
Monthly PDF export is one file per property, never merged
Portfolio dashboard is a list of property rows with drill-down

security for property, step by step

01 / 05

Top SERP framing

ADT, Vivint, SimpliSafe, Brinks, Allied. Every result is a camera kit, a sensor kit, or a guard-hour contract. The property is a shipping address.

The SERP sells cameras. The unit of risk is the property.

Run the search. Ten top results, nine of them catalogs. Camera kits priced per camera. Sensor kits priced per sensor. Guard contracts priced in hours. Every product page assumes the buyer is shopping for components to plug into a space, and the space itself (the property) is never the product. It is the shipping address on the cart, the row in the billing system, the metadata tag on the hardware order.

The buyer does not think that way. A regional property manager with 40 Class B multifamily buildings thinks in properties. A risk underwriter pricing a policy thinks in properties. An owner reviewing a monthly incident report thinks in properties. An insurer reading an after-the-fact claim thinks in properties. The on-call pager that goes off at 2am for a tailgating event is routed to the person responsible for that property, not the person responsible for that camera.

When the product's schema matches that (property as primary key, not metadata), every downstream operation lines up. When it does not, the product team and the customer are always translating. Translation is where incidents get missed.

The five places property_id is the primary key on a Cyrano deployment

Not a tag. Not a filter. The indexed, non-null, required column in every record each of these systems emits. If property_id is missing, the record does not get written.

Alert routing

The router looks up property_label to find the on-call schedule, the preferred channel (SMS, voice, dashboard toast), and the escalation chain for that specific property. A tailgating event at Bldg C does not page the oncall for Pine Hill.

Incident rollup

The nightly job GROUP BY property_id produces per-property counts, trends, and heatmaps. Building C's monthly report shows only Building C's events, not a portfolio dump filtered after the fact.

Quiet hours

The schedule is keyed to property_id because each building's mailroom opens at a different time. Building C garage alarms mute 23:00–05:30 local while Building A garage alarms mute a different window.

Monthly PDF export

One file per property, named with the property_label and the month. oak-ridge-bldg-c-2026-04.pdf has only Bldg C's incidents, is sent to Bldg C's insurer, and never blends with another building's records.

Billing and contracts

One hardware order, one subscription line, one monitoring contract per property_id. No per-camera multiplier. A 6-camera property and a 24-camera property are the same line item: one Cyrano unit.

The one file that seats property_label

This is what gets written to the unit's real disk the first time the maintenance tech submits the bind form on their phone. After this write, nothing in the downstream event path ever asks the box "what property are you." The box knows. Every event it emits carries property_label from this file as a header.

/var/lib/cyrano/provisioning/status.json

What a property-scoped alert route looks like on the wire

From the detector inside the Cyrano unit to the phone that buzzes. The router does not care which camera fired. It cares which property_label the unit reported, and it looks up the recipients from that property's configured chain.

event path, scoped to one property

cyranodalert_routerproperty_configon-call phoneevent{property_id, type=tailgating}lookup(property_id)recipients + channelsms: 'Oak Ridge Bldg C, 2:48am'ack + resolved=truerecord.scope = property_id

Per-camera pricing vs per-property pricing

The billing unit should match the risk unit. When a property manager is charged per camera, the twelfth camera that would close the garage blind spot is another monthly line, and the easiest way to save $150 a month is to leave the blind spot open. When the billing unit is the property, that same camera closes the gap at no added monthly cost, because it shows up as another tile in the same inference pipeline on the same unit.

FeatureSmart-camera SaaS (per-camera)Cyrano (per-property)
Primary billing unitPer camera, per monthPer property: $450 hardware + $200/month
Cost of adding one cameraRoughly $100–$200/month added$0/month added (up to 25 feeds per unit)
Primary schema keycamera_id, property is a tagproperty_id, cameras are tiles on the unit
Alert routing fieldGlobal recipients, property is a filterrecipients[] keyed on property_id
Incident rollup scopePortfolio view, property is a filter chipOne rollup per property, nothing crosses
Monthly report artifactPortfolio CSV with a property columnOne PDF per property, named property_label-YYYY-MM
Owner/insurer deliverableFiltered portfolio exportSingle-property PDF, no other properties visible

Portfolio dashboard fans out to property rows, each backed by one unit

Incident events
Alert confirmations
Camera tile telemetry
Quiet-hours state
Portfolio dashboard
Row: Oak Ridge Bldg C
Row: Pine Hill Main
Row: Laurel Park
Row: Cedar Court A

A property-scoped operator session

The console below is a filter to one property. Every record returned has property_id indexed; no record exists in the event store without one. The rollup at the bottom is the same aggregation that generates the monthly PDF header block.

cyctl events --property prop_oakridge_c
1 row

At one Class C multifamily property in Fort Worth, Cyrano caught 20 incidents including a break-in attempt in the first month. Every one of those 20 incidents appears on exactly one dashboard row: the row for that property_id. The on-call for that property was the only person paged; the insurer for that property was the only recipient of the monthly PDF.

Cyrano field notes, Fort Worth property

The full operator query against one property

Here is the same command above as a standalone block, because this is the shape every on-device tool and every dashboard call takes: the property_id is the required first argument, not a trailing filter. Leaving it out is a command error, not a default-all.

cyctl session, property-scoped
0Cyrano unit per property
0max camera feeds per unit
0PDF export per property per month
0$/month, per property (not per camera)

Across more than 0+ production property installs, the data path has kept the same shape: property_label seated once in status.json, carried as a header on every event, read by four downstream systems, and aggregated into one row on the portfolio dashboard.

Places property_id is the required field, not a tag

status.json header
alert_router lookup key
incident rollup GROUP BY
quiet-hours schedule scope
monthly PDF filename slot
export_targets[] scope
portfolio dashboard row id
drill-down URL param
cyctl required --property
billing line anchor
retention policy key
on-call schedule scope

Every one of these is a required field, not a nullable tag. A record without property_id is not written.

The thing that is uncopyable

property_label is written once, and never rekeyed by a camera.

On a Cyrano unit, /var/lib/cyrano/provisioning/status.json is the file where property_label lives. The on-device captive portal writes it once at bind time, the tech's phone submits it, it persists on real disk across reboots, and every downstream system (alert router, incident rollup, quiet-hours engine, monthly PDF export) foreign-keys off it. No camera can rewrite it. No event can overwrite it. When the property changes ownership, exactly two fields change (account_email and sometimes property_label), and the incident history stays attached because property_id is the stable row ID across that change. The file is the anchor. The property is the row.

When the SERP framing is fine, and when this one matters

For a single-family homeowner buying their first smart camera, the SERP framing is fine. The camera is the product. The "property" is implicit and unambiguous because there is one of them.

For a regional property manager running 40 Class B or C multifamily buildings, a construction company watching 8 job sites, or an asset manager rolling up incident trends to ownership and to the insurer, the per-camera framing falls apart. The buyer needs property as the primary key so the alerts, the reports, the exports, and the bills all agree on what a property is. That is the window this page is for, and that is the window status.json, alert_router, the rollup job, the quiet-hours engine, and the monthly PDF pipeline were shaped to fit inside.

Watch a property-scoped console drill from 40 rows to one

A 15-minute call. We open a live portfolio dashboard, click one property row, and show every alert, every incident, and this month's export all keyed on that one property_id.

Book a call

Security for property: frequently asked questions

What does the top SERP for 'security for property' actually sell?

Hardware bundles and service hours. ADT and Vivint and SimpliSafe list camera kits, sensor kits, and monthly monitoring. Brinks and Alert360 list equipment tiers. Allied Universal and Securitas list guard hours. Forbes and Safewise rank those products against each other. Every result is a list of things that plug into a property, with the property itself treated as the shipping address and the billing row. None of them describe how the system groups incidents per property, routes an alert to the right person per property, or emits an exportable monthly record scoped to a single property. The property is a tag on a cart line item. It is not the primary key.

What does it mean that property is the primary key in a security system?

It means every record the system produces has a property_id column that is never null, never a default, never inferred from a camera, and never a shipping-address afterthought. Alerts are routed by property_id, not by camera_id, so a 3am tailgating event at Oak Ridge Apts Building C pages the on-call for Oak Ridge, not the oncall for Pine Hill across town. Incident rollups are grouped by property_id, so Building C's monthly report shows only Building C's events. Quiet hours are configured per property_id because the mailroom in one building opens at 6am and the mailroom in another opens at 8am. Exports are generated per property_id because an insurer for Building C wants exactly one PDF, not a portfolio dump filtered by metadata.

Where does property_label actually get written on a Cyrano deployment?

In one file on the unit itself. /var/lib/cyrano/provisioning/status.json is written by the on-device captive portal the first time the maintenance tech submits the bind form on their phone. The JSON object has a property_label field (for example 'Oak Ridge Apts, Bldg C'), a device_id, an account_email, a bound_at_unix timestamp, and the WiFi config. That file lives on real disk (not tmpfs) so a reboot mid-install resumes in place. Every downstream event the unit emits carries the property_label from that file as a header. The cloud side never asks the box 'what property are you' because the box knows.

What specific downstream systems read property_label from that file?

Four that matter for operations. First, the alert router: when a tailgating or loitering event fires, the router looks up property_label to find the on-call schedule, the preferred notification channel (SMS, voice, dashboard toast), and the escalation chain specific to that property. Second, the incident rollup job: nightly it GROUP BY property_id to produce per-property counts, per-property trend lines, and per-property heatmaps. Third, the quiet-hours engine: it applies the schedule keyed to property_id so Building C's garage is not alarm-muted when Building A's garage is. Fourth, the monthly export pipeline: it generates one PDF per property_id with the property_label in the filename and in the header block.

Why is one Cyrano unit per property the correct boundary?

Because the property is the smallest unit that owns its own risk, its own insurance policy, its own lease contracts, and its own on-call rotation. Splitting below that level (one unit per building within a property, one unit per wing) fragments the incident log across devices that no single report can reconcile. Sharing above that level (one unit for a portfolio) means every per-property configuration (quiet hours, alert routing, notification channel, retention policy) has to be encoded into tags that the product cannot enforce at the process boundary. The unit scoped to one property exactly matches the scope at which an owner or asset manager thinks about security. It keeps the data model honest.

How does the portfolio dashboard relate to the per-property rows?

The dashboard is a list of properties, one row per property, each row backed by exactly one Cyrano unit. Click a row and the drill-down is scoped to that property: the cameras on that property, the incidents at that property, the monthly incident trend for that property, the last export for that property, and the alert recipients for that property. Nothing at the portfolio level holds raw events; raw events live on-device at the property. The portfolio view is aggregations, one row per property_id, and the aggregations are GROUP BY the same property_label that was written into status.json at bind time.

Why is per-camera pricing wrong for property security?

Because the thing an owner is actually buying is coverage for a property, not utility for a camera. A property with 6 cameras and a property with 24 cameras both have one mailroom, one lobby, one parking lot, one after-hours on-call. The risk profile is property-scoped. When security is priced per camera, a property manager is discouraged from adding the twelfth camera that would close the garage blind spot, because the twelfth camera is another $150 per month. When security is priced per property, that same garage blind spot gets closed for free, because the new camera just shows up as another tile in the same inference pipeline on the same unit. The same dynamic applies to reporting, alert recipients, and export obligations: they are all property-scoped, so the pricing should be too.

What specifically is in the monthly PDF export, and how is it scoped?

One PDF per property, named with the property_label and the month (for example 'oak-ridge-bldg-c-2026-04.pdf'). The header block shows the property_label, the property address, the device_id of the unit installed there, the month, and the count of incidents. The body is a chronological list of incident cards, each with a thumbnail, the AI classification (loitering, tailgating, package removal, vehicle entry outside hours), the tile camera the event came from, the timestamp local to the property, and the resolution note from the on-call. The rollup section has per-incident-type totals and the week-over-week delta. The cover page is built from exactly the fields in status.json and the aggregation tables keyed on property_id.

What happens when a property changes ownership or asset manager?

Two fields in status.json get rewritten: account_email and (if the property trades names) property_label. The device_id does not move; the Cyrano unit stays bolted to the shelf. The history of incidents stays attached to the property_id, so the new owner inherits a month of baseline data on day one and can see trend lines starting before they closed. The old owner's dashboard row disappears from their portfolio view when account_email flips. The bound_at_unix timestamp records when the rebind happened, so an auditor can draw a clean before/after line across a sale or a management change.

What does this look like at a portfolio of 40 Class B multifamily properties?

Forty rows on the portfolio dashboard. Forty Cyrano units on forty shelves, one per property. Forty /var/lib/cyrano/provisioning/status.json files, each with a different property_label. Forty on-call rotations, forty quiet-hours schedules, forty monthly PDFs each month. The regional manager sees all forty rows at once with incident counts, change versus last month, and the unit's live boot_phase; clicking any row drills into that property's specific feed and leaves the other 39 untouched. No cross-property mixing in the data path, no shared camera_ids across properties, no ambiguous alerts. The schema matches the org chart.

🛡️CyranoEdge AI Security for Apartments
© 2026 Cyrano. All rights reserved.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.