School Bus Home — Data Storage & Data Flow

Last updated: 11 August 2026.

This page documents where School Bus Home (operated by Erbacci LLC, a company registered in Wyoming, United States) stores data and how data moves through the system. It exists to answer the Ring privacy review's data-flow questions and is referenced from the certification questionnaire. Contact: info@erbacciltd.com.

School Bus Home performs snapshot classification and keeps no image in its data stores. On a motion or doorbell event inside one of the customer's windows it makes one vision attempt, which retrieves up to 3 still image snapshots (2 seconds apart, stopping early once the check can answer) from the Ring device via the Ring Partner API, runs a two-stage computer-vision check to decide whether a US yellow school bus is visible, and discards its copy of every image immediately after classification.

There are two windows, and they share this one pipeline:

Snapshot volume is budgeted per day and per window, and the budget is expressed in vision attempts, which is not the same as still images: 12 vision attempts for the after-school window (unchanged) and 4 for the morning window, and each window stops as soon as a bus is confirmed. One attempt re-samples up to 3 still images taken 2 seconds apart at the event moment — Ring's upload of the event can lag and a bus can be mid-turn or out of frame in the first frame — and it stops early as soon as it can answer. The worst case per customer per school day is therefore about 12 × 3 = 36 still images with the morning window off, and about 16 attempts = 48 still images with it on.

These are per-window spend bounds, not exact admission control, and we state them that way deliberately. The attempt counter is advanced when an attempt completes, while the decision to start one reads that counter beforehand, so a burst of near-simultaneous events can start a few attempts against a count that has not caught up yet and push a window slightly past its budget before it closes. The overshoot is bounded by how many attempts are in flight (the worker runs at a fixed reserved concurrency), it is small, and it does not change anything about retention. The single-notification guarantees are a different mechanism — conditional single-claim writes, not counters — and those are exact.

Every one of those images is classified in memory. The ones that show no school bus are discarded immediately; only the single image that confirms a bus is kept, on the terms set out above. The retention commitments below are unaffected by the count. Events outside every window fetch nothing at all: the after-school window is evaluated first and wins, and the morning window is consulted only for events outside it.

No video, clips, live view, audio, or biometric data ever enter the system, and no image is ever written to any database or log. Every frame that does not confirm a school bus is discarded in memory. The single frame that confirms one — at most one per window per day — is written to a private, encrypted S3 bucket (see section A), where it expires automatically after 31 days and is served only to the account owner through a short-lived pre-signed URL; alongside it the derived result (a boolean "school bus present", a confidence value, and timestamps) is persisted. No person, face, age, or licence-plate recognition is performed at any stage; the question is vehicle type only. Each stage runs its model only to answer that stage's question about the single frame in front of it: the stage-1 model on our own GPU server and the stage-2 model on Amazon Bedrock are both used for inference only, and Erbacci LLC uses no customer image to train, fine-tune, or improve any model — not the stage-1 model on the GPU server we own in the United Arab Emirates, and not through the AWS inference services we call, which under their terms do not train on customer content.

A. Data storage locations and systems

All persistent storage is in Amazon Web Services, region us-east-1, encrypted at rest with AWS-managed keys. DynamoDB tables use on-demand capacity; point-in-time recovery is enabled on the durable state tables (users, days, devices, push-tokens), while the short-lived TTL tables (one-time codes, link codes, webhook dedupe) and the voluntary waitlist do not use it.

The only component outside AWS is the stage-2 school-bus classifier (see section B): a reverse proxy on a rented Contabo GmbH virtual server in Germany in front of a GPU server Erbacci LLC owns and operates in the United Arab Emirates. It is a processing step, not one of the application's storage systems: it receives the frame in order to answer the school-bus question and returns that decision and a confidence value, and no School Bus Home table, bucket, or log is hosted there — no account, credential, schedule or detection record ever leaves us-east-1. The frame is processed transiently at both hops for the single vehicle check and is not retained, under the same no-media-retention commitment as our AWS systems.

StoreContentsRetention
school-bus-home-users (DynamoDB)Account (email, Ring account id, encrypted Ring OAuth tokens), embedded arrival schedule (after-school window times, expected-by, school days, timezone; plus the optional morning window's start/end and on/off flag — no expected-by), notification preferencesUntil account deletion
school-bus-home-days (DynamoDB)One record per user per school day: detection status, first school-bus-confirmed timestamp, detection confidence, classifier model name, frozen window snapshot, and — when the morning window is on — a separate morning sub-record (first sighting timestamp, confidence, attempt count) — no image bytes31 days (TTL, automatic expiry)
schoolbushomestack-proofframes… (S3)The single still image that confirmed a school bus — at most one per window per day, per user. Private bucket: all public access blocked, encrypted at rest (SSE-S3), TLS required. Never public; served to the account owner only, through a short-lived pre-signed URL. No frame that failed to confirm a bus is ever written here31 days (S3 lifecycle rule expire-with-day-row, automatic expiry — the same horizon as the day record it belongs to), or immediately on account deletion
school-bus-home-devices (DynamoDB)Device id, user-assigned name, type, online/offline statusUntil device removed or account deleted
school-bus-home-push-tokens (DynamoDB)APNs/FCM push endpoints per installUntil unregistered or account deleted
school-bus-home-otp-codes (DynamoDB)Salted scrypt hashes of sign-in one-time codes10 minutes (TTL)
school-bus-home-oauth-codes (DynamoDB)Unclaimed Ring link tokens + single-use session codesShort TTL (minutes)
school-bus-home-webhook-dedupe (DynamoDB)Webhook request ids for idempotency~24 hours (TTL)
school-bus-home-waitlist (DynamoDB)Email addresses voluntarily joined to the Family waitlistUntil removal requested
AWS Secrets ManagerRing client credentials, webhook HMAC secret, JWT signing secret, Resend API keyOperational
Amazon CloudWatchDiagnostic logs (labels, confidence, timing — never image data)30 days
Amazon S3 + CloudFrontStatic web dashboard assets only — no customer dataOperational

There is no media storage anywhere in the application estate above: image snapshots are held only in the worker's memory for the duration of the classification and then discarded. Nothing writes an image, base64, or embedding to any store. The stage-1 pre-scan is shown a copy of the frame in order to answer the vehicle question and returns only boxes and confidence; that copy passes through the Contabo-hosted reverse proxy in Germany and is processed transiently on the Erbacci-owned GPU server in the United Arab Emirates for the single vehicle check, and is not retained at either hop — the same no-media-retention commitment as our AWS systems.

B. Data flow between systems

Ring Partner API
   │  webhook POST (motion_detected, button_press, device_online/offline,
   │  device_added/removed, app_integration_added/removed — metadata)
   ▼
AWS Lambda (webhook-handler)   ── verifies the HMAC signature on the raw body,
   │                              deduplicates on the request id, returns 200
   ▼
Amazon SQS (events queue)
   ▼
AWS Lambda (event-processor)   ── resolves the account, checks the event against
   │                              the after-school window first, then (only if the
   │                              event falls outside it) the optional morning
   │                              window — deterministic time comparison. If it is
   │                              inside a window and within THAT window's daily
   ▼                              ATTEMPT cap (12 after-school / 4 morning), it
Amazon SQS (vision queue)         enqueues ONE vision job tagged with its window
   ▼
AWS Lambda (vision-worker)     ── ONE attempt = UP TO 3 still image snapshots from
   │                              Ring (image download API, 2s apart, stopping
   │                              early once answerable). Each frame runs two stages:
   │
   │  STAGE 1 — coarse "is a road vehicle present?" (INSIDE AWS, every frame)
   ├──► Amazon Rekognition        ── DetectLabels in us-east-1. The frame is passed
   │                                 in the request and is not persisted. A frame
   │                                 with NO vehicle stops here and is never sent
   │                                 outside AWS. (LOCAL_INFERENCE=off)
   │
   │  STAGE 2 — fine "is this a US yellow school bus?" (OUTSIDE AWS)
   ├──► vision.erbacciltd.com     ── TWO HOPS, both OUTSIDE AWS: (1) a reverse proxy
   │      │                          on a virtual server RENTED FROM CONTABO GmbH in
   │      │                          GERMANY, which TERMINATES THE TLS (so Contabo is
   │      │                          an infrastructure sub-processor able to see the
   │      │                          frame in transit; it runs no analysis), then
   │      │                          (2) the GPU server ERBACCI LLC OWNS AND OPERATES
   │      │                          in the UNITED ARAB EMIRATES, which runs the
   │      │                          classifier (qwen3.5).
   │      │                          Called as POST /schoolbushome/classify over
   │      │                          HTTPS/TLS with a bearer token (the endpoint
   │      │                          answers 403 without one). Returns ONLY the
   │      │                          school-bus decision and a confidence value.
   │      │                          THIS is where the final answer is produced.
   │      │                          The frame is processed transiently there for
   │      │                          this one check and is not retained.
   │      │  on error / timeout / unreachable  (circuit breaker after
   │      ▼  5 consecutive failures)
   │    Amazon Bedrock            ── automatic fallback, inside AWS: Anthropic's
   │                                 Claude Haiku 4.5 answers instead
   │
   │                              the worker then DISCARDS its copy of every frame
   │                              and writes only boolean + confidence + timestamp.
   │                              A confirmed bus in the MORNING window writes the
   ▼                              morning sighting instead and queues its own alert
Amazon DynamoDB
   ▼
Amazon SQS (notifications queue)
   ▼
AWS Lambda (notification-dispatch)
   ├──► Resend        — email delivery (recipient address + notification text only)
   └──► Amazon SNS    — mobile push via Apple APNs / Google FCM
                        (push token + notification title/body only)

A once-per-minute scheduled check (arrival-sweep) evaluates whether a user's expected-by time has passed with no school bus confirmed and, if so, dispatches the heads-up through the same notification path. That sweep is after-school only — the morning window has no expected-by time and no sweep, so a morning with no detection produces no notification at all, only an attempt counter on the day record. Both single-alert guarantees are enforced by conditional single-claim writes on the day record (one for the after-school arrival, a separate one for the morning sighting), so each can fire at most once per day; a morning sighting whose claim resolves at or after local noon is still recorded on the day but sends nothing, so the copy is never out of date with the clock. A daily job refreshes Ring OAuth tokens.

Every image snapshot exists only transiently in the application: each of the up-to-3 frames in an attempt is fetched, downscaled, classified, and the worker's copy is then discarded. Inside AWS none is ever persisted and none is ever written to a log line — CloudWatch records labels, confidence and timing only, never image data. Each frame is sent to exactly two destinations — (a) the AWS inference services: Amazon Rekognition for the stage-1 vehicle pre-scan on every frame, and Amazon Bedrock running Anthropic's Claude model when it answers the school-bus question as the stage-2 fallback; and (b) the stage-2 school-bus classifier (POST https://vision.erbacciltd.com/schoolbushome/classify), which is a reverse proxy on a rented Contabo GmbH virtual server in Germany that terminates the TLS, in front of the GPU server Erbacci LLC owns and operates in the United Arab Emirates. Across both of those hops the frame is processed transiently for that single school-bus question and is not retained, under the same no-media-retention commitment as our AWS systems. A Ring device with an active cloud recording (Ring Protect) plan is required for a still image to exist at the event moment; when none exists, the app records "detection unavailable" for that camera and does not report a false result.

Ring API calls made by the system (exhaustive): POST https://oauth.ring.com/oauth/token, GET /v1/users/me, GET /v1/devices (with ?include=status), GET /v1/devices/{id} (single-device metadata refresh when a device name/status needs healing), POST/PATCH /v1/accounts/me/app-integrations, and POST /v1/devices/{id}/media/image/download (retrieves a still image snapshot, called up to 3 times per vision attempt; every frame is classified in-memory and discarded). No live-view, clip, or event-history endpoint is ever called.

Third parties receiving data: AWS (infrastructure, Amazon Rekognition which performs the stage-1 vehicle pre-scan on every frame, the Amazon Bedrock inference service which answers the school-bus question when it is the stage-2 fallback, and push dispatch), Anthropic (its Claude model performs the school-bus classification within Amazon Bedrock when Bedrock answers; it receives the transient image for that inference only, does not retain it, and does not train on it), Contabo GmbH (the German hosting provider whose rented virtual server runs the TLS-terminating reverse proxy in front of the stage-2 classifier; the frame passes through it in transit and it performs no analysis and holds no account data), Resend (email address + notification content), and Apple/Google (push token + notification title/body). None of these third parties retain the image and none use the data for any other purpose.

The stage-2 analysis itself is not an onward disclosure to another company: it runs on a GPU server Erbacci LLC owns and operates. It is listed separately from the third parties above because it is first-party processing — but it takes place in the United Arab Emirates, outside the United States, which is disclosed as such in the privacy policy rather than presented as an in-AWS step.

Deletion: in-app Settings → Delete account cascades across all tables immediately; unlinking the integration in the Ring app revokes our access immediately; requests can also be made via info@erbacciltd.com.

C. Contact

Erbacci LLC · info@erbacciltd.com