🔒

Admin Only

This page is restricted to Wilton CERT administrators.

Collections
👤
Collection
members
Read All signed-in members Write Admin only
The central roster of every CERT member. Document IDs are auto-generated by Firestore. Each document represents one person and is the source of truth for contact info, certifications, and member status. Many other collections reference back here by document ID.
Active status is not a stored field — it is computed from oathdate. A member is considered active if their oath date is within the past 730 days (2 years). If no oath date is recorded, status defaults to inactive.
FieldTypeDescription
firstnameStringMember's first name.
lastnameStringMember's last name.
emailStringMember's email address. Used to match Firebase Auth sign-ins to member records.
phoneStringMember's phone number, stored as a formatted string.
streetStringStreet address (e.g., "123 Main St").
cityStringCity of residence.
stateStringState abbreviation (e.g., "CT").
zipStringZIP code.
joindateString (YYYY)Year the member joined Wilton CERT. Used for display only.
oathdateString (YYYY-MM-DD)Date the member took their CERT oath. Drives the active/inactive status calculation. A member is active if this date is within the past 2 years.
certificationsString[]Array of certification labels held by this member. Controls what roles they can fill at events and what appears on the Officers page. Common values: Driver, TC (Training Captain), DC (Deployment Captain), DDC (Deputy DC), PC (Post Captain), Training Officer, Logistics Officer, Communications Officer, etc. Any value ending in Officer automatically appears on the officers roster.
notesStringFree-text admin notes about the member. Only visible on the Members admin page.
uidStringFirebase Authentication UID. Set automatically when an admin creates a sign-in account for the member. Not present on older or account-less records.
createdAtTimestampServer timestamp set when the member record was first created.
updatedAtTimestampServer timestamp updated on every save.
🔑
Collection
administrators
Read All signed-in members Write Admin only
Controls who has administrator access to the site. Document IDs are the member's email address in lowercase. When a signed-in user visits any admin page, the app looks up their email in this collection. If a matching document exists and active is not false, they are granted admin access.
To revoke admin access without deleting the record, set active to false. To grant access, create a document here with the member's lowercase email as the document ID.
FieldTypeDescription
activeBooleanWhether this admin account is currently active. If missing, treated as true. Set to false to suspend access without deleting the record.
adminRoleString (optional)Informational label for the admin's role (e.g., "super", "blog"). Not currently used to gate features — all active admins have equal access.
📋
Collection
events
Read All signed-in members Create/Update Admin Officers / event managers Delete Super only
The single collection for all CERT events — planned deployments, unplanned deployments, and training. The type field distinguishes them. Document IDs are generated on creation as YYYY - Event Name (e.g., "2026 - Pumpkin Parade"). Volunteer sign-ups and shift definitions are not embedded here — they live in the separate shifts and signups collections, linked back by eventId.
Three event types. type: "planned" and type: "unplanned" are managed on the Deployments Admin page; type: "training" on the Training Admin page. Member-facing pages filter by this field. Deployment Officers may create/edit planned & unplanned events; Training Officers may create/edit training events; event managers (listed in managerEmails) may edit their own event.
FieldTypeDescription
typeString"planned", "unplanned", or "training". Controls which admin and member pages show the event and which officer role may manage it.
nameStringEvent name as displayed to members. Part of the document ID.
dateString (YYYY-MM-DD)Date of the event; used for sorting and display.
statusString"open" — accepting sign-ups; "closed" — locked. TC/DC users do not see closed events.
locationStringAddress or place name. For virtual training, a GoTo Meeting URL (meet.goto.com/…) that triggers the virtual-meeting UI.
descriptionStringOptional free-text shown to members on the sign-up page.
numPostsNumber (deployments)Number of named field posts; controls the numbered post options in the roster post-assignment dropdown.
managersObject[]Event leaders. Each entry is { memberID, email, title } where title is DC / DDC / TC / DTC. Edited in the Managers section of the event form.
managerEmailsString[]Lowercase emails of the current managers. Auto-computed from managers; used by Firestore rules to grant managers edit access without a members lookup.
documentsObject[]Attached document references (name + URL) shown in the event's Documents section.
Insurance Activation Fields
FieldTypeDescription
activationString"state" (default), "town", or "none" — the insurance activation type. Managed on the Insurance Activations page.
actStartString (datetime-local)Activation window start, e.g. "2026-06-29T07:00". Empty when activation is none.
actEndString (datetime-local)Activation window end, e.g. "2026-07-06T19:00".
submittedBooleanActivation paperwork submitted to the insurer.
receivedBooleanConfirmation received back from the insurer.
actAdmin scope. Holders of the actAdmin role may update only the five activation fields above (activation, actStart, actEnd, submitted, received) — the Firestore rules reject any other field change from that role.
Cascade delete. Deleting an event (super only) also deletes its shifts and signups. Events can instead be snapshotted to eventBackups via the super-only Backup button.
🕒
Collection
shifts
Read All signed-in members Write Admin Officers / event managers
Shift definitions for events. One document per shift, linked to its event by eventId. Training events have a single shift; deployments may have several. Document IDs are {eventId}-{title}. Deleting a shift cascades to its sign-ups.
FieldTypeDescription
eventIdStringDocument ID of the parent events record.
titleStringShift name shown to members (e.g., "Morning", "Class").
startTimestamp / ISO stringShift start time.
endTimestamp / ISO stringShift end time.
certsNeededNumberTarget number of certified volunteers (display only — not a hard cap).
driversNeededNumberTarget number of certified drivers for the shift.
Collection
signups
Read All signed-in members Create Any signed-in member Update/Delete Admin Managers Self (own / unconfirmed)
One document per volunteer-shift pairing — the volunteer roster. Document IDs are {shiftId}-{memberID}, so a member can appear at most once per shift. Members create their own sign-ups; they may delete an unconfirmed one or update only confirmedAt / hoursLogged (rules-enforced). Admins and event managers may edit any sign-up.
FieldTypeDescription
eventIdStringDocument ID of the parent events record.
shiftIdStringDocument ID of the shifts record this sign-up is for.
memberIDStringDocument ID from the members collection.
certRoleStringRole at this event: VOL, PC, DDC, DC (deployments), TC (training), or Driver. Defaults to VOL.
postString (deployments)Post assignment: "NA" (unassigned), a special code from specialCodes (e.g. "CC"), or a post number as a string.
truckString | nullAssigned truck ID (from trucks) when certRole is Driver; otherwise null.
hoursLoggedNumberHours credited to the volunteer for this shift (set on the roster/hours pages).
confirmedAtString (ISO) | nullTimestamp set when the member confirms attendance on the sign-up page; null until confirmed. A confirmed sign-up can no longer be self-deleted.
📰
Collection
blog-posts
Read All signed-in members Write Admin only
Stores all blog/activity posts. Document IDs are auto-generated. Six post types share this collection; some fields are only relevant to specific types.
Universal Fields (all post types)
FieldTypeDescription
titleStringPost headline displayed in lists and on the post page.
typeStringPost category. Controls layout and which sections appear. Values: planned, unplanned, training, weather, commendation, special.
dateString (YYYY-MM-DD)Date of the event or post. Used for sorting and display.
summaryStringShort summary shown on the blog list page (1–2 sentences).
bodyStringFull narrative of the event in plain text / basic markdown. Shown on the post detail page.
tagsString[]Array of tag strings for filtering (e.g., ["Parade", "Traffic"]).
statusString"published" — visible to all members; "draft" — only visible to admins on the blog admin page.
membersObject[]CERT members who participated. Each entry: { id, name, role } where id references the members collection, name is a display string, and role is the role they held at that event.
otherAttendeesString[]Free-text names of non-member attendees or partner agencies.
othersHeaderStringSection heading for the otherAttendees list (e.g., "Wilton Police Department").
photoFolderStringFirebase Storage path to this post's photo folder (e.g., blog-photos/blog_abc123). All uploaded images for this post live under this path.
createdAtTimestampServer timestamp set on first creation.
Type-Specific Fields
FieldTypeOnly forDescription
timeStringweatherTime of the weather event (e.g., "2:30 PM").
pdfUrlStringweatherURL to a PDF storm summary document.
personNameStringcommendationFull name of the person being commended.
personPhotoUrlStringcommendationURL to a photo of the person being commended.
commendationUrlStringcommendationURL to the commendation certificate or supporting document.
certMembersString[] legacyolder postsDisplay names of attendees in older posts, before the structured members object array was introduced. Still rendered on old post pages that pre-date the new format.
🏛️
Collection
board
Read Public Write Admin only
Stores the elected board / leadership team. Shown on both the public Leadership page and the members-only Leadership & Bylaws page (with contact info on the members version). Document IDs are auto-generated. The footer also reads this collection to display the Executive Director's phone number. Managed on the Board of Directors admin page (board_admin.html), which also grants each active board member view-only access to CERT Finance by writing a financeOfficers/{email} entry with canWrite: false and viaBoard: true (resolved from the member's memberIDmembers email). Removing or deactivating a board member deletes that synced entry; manually-added Finance Officers (without viaBoard) are never touched.
FieldTypeDescription
firstnameStringBoard member's first name.
lastnameStringBoard member's last name.
roleStringBoard position. Special values that control sort order: "Executive Director" (always first), "Deputy Executive Director" (always second), "Director" (sorted by term end date).
activeBooleanSet to false to hide a member from the leadership display without deleting the record. Defaults to active if omitted.
termEndsString (M/D/YYYY)Term expiration date, e.g. "12/31/2029". Shown on the leadership card and used to sort Directors (soonest-expiring first). The Board admin page converts to/from the <input type="date"> format automatically.
memberIDStringDocument ID from the members collection. Used on the members-only page to fetch the board member's phone and email for the contact modal.
phoneStringPhone number. Read by the site footer to show the Executive Director's contact number in the footer contact block.
🎖️
Collection
officers
Read Public Write Admin only
A denormalized snapshot of appointed officers for the public leadership page. Because the public page cannot access the members collection (sign-in required), this collection holds a pre-computed copy of officer data. It is populated and kept in sync by the Sync Officers admin tool, which scans the members collection for any certification ending in "Officer" and writes a record here for each one.
Do not edit this collection manually. Use the Sync Officers admin tool after updating member certifications. Manual edits will be overwritten the next time the sync runs.
FieldTypeDescription
firstnameStringOfficer's first name (copied from members).
lastnameStringOfficer's last name (copied from members).
roleStringOfficer title derived from their certification (e.g., "Training Officer", "Deputy Logistics Officer").
activeBooleanWhether this officer is currently shown on the leadership page. Set by the sync tool based on member active status.
sortOrderNumberDisplay order on the leadership page. Set by the sync tool based on role name and deputy status.
memberIdStringDocument ID from the members collection that this officer record was generated from.
🏷️
Collection
roles
Read All signed-in members Write Admin only
A lookup table that maps role abbreviations to human-readable labels, used in blog post creation and display. If a read fails, the app falls back to a hardcoded default list.
FieldTypeDescription
abbrevStringShort role code displayed on volunteer rosters and blog posts. E.g., VOL, TC, DC, DDC, PC, DTC.
labelStringFull human-readable label. E.g., "Volunteer", "Training Captain", "Deployment Captain".
sortOrderNumberDisplay order in role selection dropdowns.
📍
Collection
specialCodes
Read All signed-in members Write Admin only
Named special post assignments for deployment events, shown in the post-assignment dropdown on the volunteer roster. Instead of being assigned to a numbered field post, a volunteer can be assigned a special post like "CERT Command." The default fallback if the collection is empty or unreadable is a single entry: CC — CERT Command.
FieldTypeDescription
codeStringShort code stored in the volunteer's post field (e.g., "CC").
labelStringFull description shown in the dropdown (e.g., "CERT Command").
sortOrderNumberOrder in which codes appear in the dropdown, before the numbered posts.
🌐
Collection
languages
Read All signed-in members Write Admin only
Stores language capabilities of CERT members, used on the Languages member page. This collection supports the community multilingual resource directory.
⚙️
Collection
settings
Read Public Write Admin only
Site-wide configuration. Currently used for theme overrides. The document settings/theme can contain CSS variable overrides that are applied globally. Public-readable so that theme settings apply to the public-facing pages as well.
💵
Collection · Finance
budgetCategories
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Per-category budget lines for the finance system, one document per category per fiscal year. Document IDs are stable: {fy} - {name} at creation — renaming changes the name field but keeps the same id, so arLines referencing the id stay linked. The FY total budget is NOT stored here — it is derived from funding sources (see sourceLines).
FieldTypeDescription
fyStringFiscal year, e.g. "2026".
nameStringCategory name (e.g., "Equipment", "Training").
budgetNumberBudgeted dollar amount for this category in this fiscal year.
💵
Collection · Finance
certFunding
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Funding sources (the "Sources" side of Sources & Uses) — grants, town allocations, donations. Document IDs are {fy} - SRC-nnn. Each source's dollar amounts live in sourceLines; the sum across non-deleted sources is the FY total budget.
FieldTypeDescription
fyStringFiscal year.
sourceNumberNumberSequential source number within the fiscal year (SRC-001, …).
sourceTypeString"Town", "Cat. A Grant", "Donation", or "Other Grant".
dateString (YYYY-MM-DD)Source date; the fiscal year is derived from it.
statusString"open" or "funded".
descriptionStringFree-text label for the source.
deletedBooleanSoft-delete flag; deleted sources are excluded from totals but can be restored.
💵
Collection · Finance
sourceLines
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Line items belonging to a funding source. Document IDs are {sourceId} - L{n}. The sum of these amounts across non-deleted sources is the derived FY total budget.
FieldTypeDescription
fyStringFiscal year (copied from the parent source for querying).
sourceIdStringDocument ID of the parent certFunding source.
lineNumberLine order within the source.
amountNumberDollar amount of this funding line.
useTypeString"General", "Training", or "Equipment" — the coarse "use" bucket.
arRefStringOptional reference to an appropriationRequests doc this funding is tied to (scoped to the source's FY).
💵
Collection · Finance
vendors
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Vendor list used to auto-complete the Vendor field on AR line items. Auto-generated document IDs.
FieldTypeDescription
nameStringVendor name. New vendors are created on the fly when typed into an AR line.
activeBooleanSet to false to hide a vendor from the picker without deleting it.
💵
Collection · Finance
appropriationRequests
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Appropriation Requests (ARs) — the "Uses" side of the budget: spending requests. Document IDs are {fy} - AR-nnn. Line items live in arLines; the AR total is the sum of its line costs.
FieldTypeDescription
fyStringFiscal year, derived from date via the configured fiscal-year-end.
arNumberNumberSequential AR number within the fiscal year.
dateString (YYYY-MM-DD)Request date; determines the fiscal year.
requesterMemberIdStringDocument ID of the requesting members record.
requesterNameStringCached requester name for display.
descriptionStringShort description of the request.
statusStringWorkflow status of the request (e.g., open).
notesStringFree-text notes.
deletedBooleanSoft-delete flag; deleted ARs are excluded from totals and Budget vs Actual but keep their lines and can be restored.
💵
Collection · Finance
arLines
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Line items belonging to an Appropriation Request. Document IDs are {arId} - L{n}. Deleting an AR cascades to its lines.
FieldTypeDescription
fyStringFiscal year (copied from the parent AR for querying).
arIdStringDocument ID of the parent appropriationRequests.
accountStringThe category ID from budgetCategories (a stable id, not the display name) — so renaming a category updates everywhere.
vendorStringVendor name (matched against vendors).
descriptionStringLine description.
quantity / amount / costNumberUnit quantity, unit price, and extended cost (quantity × amount).
basisString"actual" or "forecast".
bookingString"booked", "notBooked", or "placeholder".
link / notesStringOptional reference link and free-text notes.
invoicesObject[]Attached invoice files (PDF/PNG/JPG) — each { name, url, path } in Firebase Storage under ar-invoices/.
💵
Collection · Finance
purchaseOrders
ReadAdmin / finance roleFinance Officers WriteAdmin / finance roleFinance Writers
Open purchase orders / encumbrances. Encumbered amount is derived (total − expensed). Auto-generated document IDs.
FieldTypeDescription
fyStringFiscal year.
poNumberStringPurchase order number.
vendorStringVendor name.
totalNumberTotal PO amount.
expensedNumberAmount already expensed; remainder is encumbered.
🔑
Collection · Access
financeOfficers
ReadAll signed-in members Create/UpdateAdmin DeleteAdminSelf
Grants finance access to people who are not full admins. Document ID is the member's lowercased email. Entries are added either manually or automatically by the board admin page (which grants board members view-only access).
FieldTypeDescription
emailStringThe member's email (also the document ID).
canWriteBooleanWhether this officer may edit finance data. Defaults to true when omitted (legacy entries keep full access). false = read-only (e.g., board members). Enforced by Firestore rules.
viaBoardBooleantrue if created by the board sync. Only viaBoard entries are auto-removed when a board member is removed/deactivated — manually-added officers are never touched.
memberID / nameStringFor board-synced entries: the linked member's ID and display name (reference only).
🔑
Collection · Access
deploymentOfficers · trainingOfficers · membershipOfficers
ReadAll signed-in members Create/UpdateAdmin DeleteAdminSelf
Three certification-synced access collections, each keyed by lowercased email. They are populated by the Sync Officers tool, which scans members for the matching "Officer" certification and writes an entry. Membership in a collection grants the scoped power: deploymentOfficers may create/edit planned & unplanned events; trainingOfficers may create/edit training events; membershipOfficers may create/edit members and memberEmails. (See also financeOfficers, documented separately because of its read/write field.)
FieldTypeDescription
emailStringThe officer's email (also the document ID). The presence of the document is what grants access — no other fields are required.
🔑
Collection · Access
memberEmails
GetPublic (single doc) ListDenied WriteAdmin / emailAdminMembership Officers
A public-readable mirror of member email addresses, keyed by lowercased email, used by the sign-in screen to check whether an email belongs to a member without exposing the full members collection. It is also the membership gate for the security rules: because Google sign-in creates a Firebase Auth account for any Google user, reads of member data (events, members, signups, shifts, …) require the signed-in email to exist here (or in administrators, for org accounts with no member record). Single-document get is allowed publicly; listing the whole collection is denied. Kept in sync when members are imported/edited.
FieldTypeDescription
emailStringThe member's email (also the document ID).
🔑
Collection · Access
authActivity
ReadAdminSelf WriteSelf only
Login activity self-reported by each user on sign-in. Document ID is the lowercased email. A user may only write their own document (rules validate the field set); admins can list/read/delete all. Powers the Login Activity admin page.
FieldTypeDescription
emailStringThe user's email (also the document ID).
createdAtString (ISO)When the activity record was first created.
firstLoginAtString (ISO)First recorded sign-in (optional).
lastLoginAtString (ISO)Most recent sign-in.
⚙️
Collection · System
certInfo
ReadPublic WriteAdmin
Organization info, stored in a single document certInfo/main. Read everywhere (including public pages); edited on the CERT Info admin page. The fiscalYearEnd drives every fiscal-year calculation in the finance system.
FieldTypeDescription
certNameStringOrganization name.
fiscalYearEndString (MM-DD)Fiscal year end, e.g. "06-30". Required by the finance system.
logoStringPath/URL to the logo image; defaults to assets/CERT_Logo.jpg.
🚒
Collection · System
trucks
ReadAll signed-in members WriteAdmin
CERT vehicles/trucks that can be assigned to drivers on a deployment roster (referenced by signups.truck).
FieldTypeDescription
nameStringTruck label shown in the driver-assignment dropdown.
activeBooleanSet false to hide a retired truck without deleting it.
sortOrderNumberDisplay order in the dropdown.
📦
Collection · System
inventory
ReadAdmin WriteAdmin
CERT equipment/asset inventory, managed on the Inventory admin page.
FieldTypeDescription
nameStringItem name.
quantityNumberCount on hand (may be blank).
statusString"Active" or "Inactive".
(additional)StringOther descriptive fields (e.g., category, location, notes) as captured on the inventory form.
✍️
Collection · System
roster_entries
Read/Create/UpdateAdminDeployment Officers / managers DeleteAdmin
Physical sign-in/out records with signatures for a deployment shift. Document IDs are {shiftId}-{memberID}, mirroring a signups record. Drives the printed roster and hours logging.
FieldTypeDescription
eventId / shiftId / memberIDStringLinks back to the event, shift, and member.
signedInAt / signedOutAtTimestampSign-in and sign-out times.
signatureIn / signatureOut / safetySigString (data URL)Captured signature images.
hoursLoggedNumberHours credited for the shift.
processedAtTimestampWhen hours were finalized/processed.
🗄️
Collection · System
eventBackups
ReadAdmin WriteSuper only
Single-document snapshots of a deployment, kept out of the live events collection. Created by the super-only Backup button; the document ID matches the original event ID. Re-running a backup overwrites it.
FieldTypeDescription
originalIdStringDocument ID of the event that was backed up.
backedUpAtString (ISO)When the snapshot was taken.
eventObjectFull copy of the event document.
shifts / signups / equipmentObject[]Copies of the event's shifts, sign-ups, and equipment at backup time.
✉️
Collection · System
mail
CreateAnyone Read/Update/DeleteAdmin
Outbound email queue for the Firebase Trigger Email extension — writing a document here sends an email. Used for notifications such as password-reset alerts.
FieldTypeDescription
toString | String[]Recipient email address(es).
messageObject{ subject, html } — the email subject and HTML body.
📝
Collection · System
intake
CreateAnyone Read/Update/DeleteSigned-in members
Submissions from the public "Join CERT" / interest form. Anyone may create a submission; signed-in members can review and manage them. Auto-generated document IDs.
FieldTypeDescription
(applicant fields)StringName, email, phone, and any message/answers captured by the join form.
🔐
Collection · System
passwordResetRequests
CreateAnyone (validated) Read/DeleteAdmin UpdateDenied
Log of password-reset requests made from the sign-in screen. Create is open but the rules strictly validate the field set and sizes; documents are immutable once written.
FieldTypeDescription
emailStringEmail that requested the reset.
requestedAtString (ISO)When the request was made.
matchesMemberBooleanWhether the email matched a known member (optional).
source / requestedByStringWhere the request originated and who initiated it (optional).
⚙️
Collection · System
config
ReadAll signed-in members Create/UpdateAdmin DeleteSuper only
Miscellaneous internal configuration documents. A key collection — only super may delete.
FieldTypeDescription
(varies)Document shape depends on the config key.
⚙️
Collection · System
seedYear
Read/Create/UpdateAdmin DeleteSuper only
Tracks the current program year for the rewards system. The document seedYear/current holds the active year.
FieldTypeDescription
yearNumberThe current rewards program year.
🔗
Reference
Key Relationships
Member Identity

A member's Firestore document ID is the link between collections. signups.memberID, events.managers[].memberID, board.memberID, blog-posts.members[].id, and officers.memberId all reference the members collection by this ID.

Admin Access Gate

The administrators collection is keyed by lowercase email. When any admin page loads, the app calls checkIsAdmin(db, user) which does a single Firestore read to administrators/{email}. No email match = no access.

DC/TC Access Gate

Event managers (Deployment Captains, Training Captains, and their deputies) are identified by their email appearing in events.managerEmails — auto-recomputed from the events.managers array (each { memberID, email, title }) whenever managers change. Firestore rules grant a manager edit access to their own event by checking this array.

Officers Sync

The officers collection is a public-readable copy of data from members. Any member certification ending in "Officer" generates an entry. Run the Sync Officers tool after editing member certifications to keep them aligned.

Active Member Status

There is no active field on member records. Active status is computed on the fly: oathdate within the past 730 days = active. Missing or older oath date = inactive. Update oathdate after re-certification to restore active status.

Photo Storage

Blog post photos are stored in Firebase Storage, not Firestore. The Storage path is blog-photos/blog_{postId}/{filename}. The Firestore document stores only the folder path in photoFolder; the app lists files from Storage at runtime.