Formerly published as "CivicClerk"; renamed 2026-07 to avoid confusion with an unrelated commercial product of that name. Package and service identifiers are unchanged.
CivicMeetings is the CivicSuite module for municipal meetings, agendas, packets, minutes, votes, notices, and public meeting archives.
Status: CivicMeetings v1.0.4 runtime foundation label is provisional during the CivicSuite release recovery.
Current version: 1.0.4
Repository: https://github.com/CivicSuite/civicclerk
Depends on: published, Sigstore-attested civiccore 1.2.1 wheel from the v1.2.1 release asset
CivicMeetings is not product-ready for public promotion while the CivicSuite
release recovery is active. Treat the current v1.0.4 recovery patch
as provisional until this repo re-earns release status through the recovery
gates: full local backend tests, frontend unit tests, real Playwright user-flow
tests, WSL runtime install proof, release consistency checks, secret/security
scans, docs-source parity enforcement, and explicit mock validation versus
production deployment labeling. Integration release depth now requires live-wire
or in-process boundary validation; adversarial mock checks are supplemental
regression coverage and are not a substitute for claiming a live production
deployment.
Persistence Phase 1 update: motions, votes, action items, minutes drafts,
public archive records, and resident comments now persist to the configured
database when CIVICCLERK_MOTION_VOTE_DB_URL, CIVICCLERK_MINUTES_DB_URL,
and CIVICCLERK_PUBLIC_ARCHIVE_DB_URL are set — set
CIVICCLERK_MEETING_DB_URL as well so the parent meeting records survive
with them — so the legal record of a meeting survives an API restart. The
public archive database must also contain the published meeting's referent
row in civicclerk.meetings (migration 0014); the publish endpoint returns
a self-describing 404 with the fix when it does not. Without those
variables CivicMeetings falls back to in-memory stores and the legal record
does not survive a restart — do not run a real public meeting without
database-backed persistence enabled. Minutes adoption/posting write paths,
transcript records, ordinance/resolution handoffs, posted notice records,
and packet snapshots remain in-memory pending Persistence Phase 1b.
CivicMeetings now wires the strengthened CivicCore release-provenance preflight
into release-class workflows. GitHub release pages can display a "Verified"
badge for the target commit even when the release tag itself is lightweight or
unsigned, so CivicMeetings treats that badge as a commit-only signal. Post-baseline
releases are verified by a Sigstore-signed release-attestation.json plus
bundle, and the exact verification shape lives in docs/ops/release-signing.md.
The prior public v0.1.20 release is a historical pre-gate artifact because
its tag predates the attestation model and its public release assets do not
include release-attestation.json or release-attestation.json.bundle. CO-4
records the decision in docs/ops/tier1-retrofit-ledger.md: do not delete,
recreate, mirror, or promote v0.1.20 as an attested provenance baseline.
CivicMeetings is designed for the legal record of public meetings:
- agenda item intake from departments
- packet assembly
- statutory notice deadline tracking
- meeting motions, votes, and action logging
- minute drafting with source citations
- ordinance and resolution adoption-event export
- public meeting pages for posted agendas, packets, and approved minutes
- searchable meeting archives
AI may draft or extract. Humans approve every consequential action.
CivicMeetings currently contains the runtime and schema foundation plus database-backed agenda item lifecycle records, meeting lifecycle, packet snapshot, shared CivicCore-backed notice compliance, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public calendar/detail/archive endpoints, a prompt YAML library with an offline evaluation harness, local-first connector imports for Granicus, Legistar, PrimeGov, and NovusAGENDA, accessibility/browser QA gates, CivicCore v1.2.1-backed records export bundles, database-backed agenda intake readiness, database-backed packet assembly records, database-backed notice checklist/posting-proof records, database-backed meeting records, and first staff workflow screens for intake, packet assembly/export, notice checklist, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. These capabilities remain under recovery validation and must not be promoted as product-ready until the recovery gates pass. The staff screens submit agenda intake, record readiness review, create/finalize packet assembly records, create records-ready packet export bundles, persist notice checklist records, attach posting proof, capture motions/votes/action items, create citation-gated minutes drafts, publish public-safe archive records, normalize local connector exports through the shared CivicCore connector import contract, surface vendor sync source health and no-network run logging, expose the shared CivicCore connector runtime validation helpers that future live-sync work can adopt without bespoke security plumbing, expose the first vendor live-sync readiness and circuit-breaker contract for future scheduled pulls, consume the shared CivicCore trusted-header config and proxy-source enforcement helpers, and expose /staff/auth-readiness so operators can verify whether OIDC, bearer, or trusted-header staff auth is deployment-ready before testing a live session. When OIDC, bearer, or trusted-header mode is ready, the readiness contract now includes a concrete protected-session probe and a protected-write probe instead of only env-var reminders, and trusted-header readiness now carries a loopback-only local proxy rehearsal contract that points operators to scripts/local_trusted_header_proxy.py with 127.0.0.1/32 as the safe starter allowlist.
Shipped in this foundation:
- project README
- user manual with non-technical, IT/technical, and architecture sections
- GitHub Pages landing page at
docs/index.html - contributing, support, security, code of conduct, issue templates, and PR template
- discussion seed posts
- docs verification script and CI workflow
- Python package metadata with the published
civiccore1.2.1 wheel from thev1.2.1release asset - first
frontend/React/Vite staff workspace slice adapted from the CivicSuite mockup into production TypeScript - live
GET /meetingsendpoint for staff calendar/list views - live
PATCH /meetings/{id}endpoint for pre-lock schedule edits with audit entries for changed scheduling fields - live
/meeting-bodiescreate/list/read/update/deactivate endpoints backed by the canonical meeting body table - FastAPI application import path at
civicclerk.main:app - root endpoint that explains the current product state
/healthendpoint for IT staff/staffstaff workflow screens with a live agenda-intake product cockpit for agenda intake, packet assembly/export, notice checklist/posting-proof, meeting outcome, minutes draft, public archive, connector import, and vendor sync work- live
/staffagenda intake submission and clerk readiness-review form actions backed by/agenda-intake - live
/staffpacket assembly create/finalize form actions backed by/meetings/{id}/packet-assemblies - live
/staffpacket export form actions backed by/meetings/{id}/packet-snapshotsand/meetings/{id}/export-bundle - live
/staffnotice checklist and posting-proof form actions backed by/meetings/{id}/notice-checklists - database-backed agenda intake queue with clerk readiness review state and
promotion linkage via Alembic migrations
civicclerk_0002_intake_queueandcivicclerk_0008_intake_promotion /agenda-intakesubmit/list/review/promote endpoints with audit events for consequential review and promotion actions- canonical SQLAlchemy metadata for the fourteen CivicMeetings tables
- Alembic scaffold and first idempotent migration for the
civicclerkschema - CC-5 canonical data model completion through Alembic migration
civicclerk_0011_data_model, adding downstream contract columns for packet version uniqueness, motion/vote correction metadata, public comment intake, closed-session ACLs, document references, transcript sensitivity, and CivicCode ordinance handoff status - agenda item lifecycle enforcement from
DRAFTEDthroughARCHIVED - optional database-backed agenda item lifecycle persistence with
CIVICCLERK_AGENDA_ITEM_DB_URL - CivicCore-verifiable persisted audit hashes for allowed and rejected agenda item transitions
- meeting lifecycle enforcement from
SCHEDULEDthroughARCHIVED - database-backed meeting records with CivicCore-verifiable lifecycle audit hashes, scheduled
starts, meeting body linkage, location, normalized meeting type, and Alembic
migrations
civicclerk_0005_meetingspluscivicclerk_0007_meeting_schedule /meetingslist endpoint for live React staff calendar loading/meetings/{id}schedule update endpoint that blocks edits once the meeting reaches the in-session lock point and returns an actionable replacement-meeting fix path- emergency/special meeting notice preconditions requiring a statutory basis
- closed/executive session in-progress preconditions requiring a statutory basis
- cancellation support from scheduled or noticed meetings, with terminal-state audit entries
- packet snapshot versioning for meetings
- database-backed packet assembly records with source references, citations,
packet snapshot linkage, and Alembic migration
civicclerk_0003_packet_asm /meetings/{id}/packet-assembliescreate/list endpoint and/packet-assemblies/{id}/finalizeendpoint with durable audit hashes- notice compliance checks for deadlines, statutory basis, and human approval
- database-backed notice checklist and posting-proof records with Alembic
migration
civicclerk_0004_notice_ck /meetings/{id}/notice-checklistscreate/list endpoint and/notice-checklists/{id}/posting-proofendpoint with durable audit hashes- approved public notice posting records with actionable warning/error responses
- immutable captured motions with seconded-by metadata and append-only correction records
- immutable captured votes with aye, nay, abstain, recusal, and absent outcomes plus append-only correction records
- action items linked to meeting outcomes and source motions
- live
/staffmeeting outcome form actions backed by/meetings/{id}/motions,/motions/{id}/votes, and/meetings/{id}/action-items - live
/staffminutes draft form actions backed by/meetings/{id}/minutes/drafts - live
/staffpublic archive form actions backed by/meetings/{id}/public-record,/public/meetings,/public/meetings/{id}/{agenda|packet|minutes}.txt,/public/meetings/{id}/comments, and/public/archive/search - live
/staffconnector import form actions backed by/imports/{connector}/meetings - citation-gated minutes draft records
- provenance for minutes drafts: model, prompt version, data sources, and human approver
- rejection of uncited AI-drafted minutes output before it can be accepted
- permission-aware public meeting calendar, detail, archive search, document download, and public comment endpoints
- resident-facing React public portal at
/publicin the Docker/nginx product path, backed by public calendar, detail, and archive search APIs - closed-session leak prevention for anonymous public archive bodies, counts, suggestions, and not-found responses
- YAML prompt library under
prompts/for agenda item summary, staff report normalization, packet completeness review, notice compliance review, motion/vote summary, minutes drafting, ordinance/resolution extraction, closed-session safe refusal, and public plain-language meeting explanation - prompt registration through
civiccore.llm.resolve_templateas CivicCore code-level overrides underconsumer_app="civicclerk" - offline prompt evaluation harness that runs with
CIVICCORE_LLM_PROVIDER=ollamaand outbound network blocked, covering citation requirements, closed-session refusal, legal-determination refusal, public approval gates, and input mutation stability - CC-7 API/frontend completeness contract with generated
docs/api/openapi.json,scripts/generate-openapi-spec.py, staff report, transcript, ordinance/resolution handoff, public comment review, admin config, and prompt admin endpoints, plus 20 direct React page routes for the spec surfaces - CC-7 browser QA evidence in
docs/browser-qa/cc7-api-frontend-completeness-qa-2026-05-06.jsonanddocs/screenshots/cc7-api-frontend-completeness-summary.md, covering all 20 pages, five QA states, desktop, 390px mobile, keyboard focus, contrast, horizontal overflow, visible copy, and console/runtime checks - prompt-version provenance enforcement for minutes drafts
- integration-depth readiness at
/integrations/readinessfor CivicRecords search, CivicCode handoff, codification export, city CMS posting, and vendor live API adapters, plus a live CivicCode handoff emitter that sends adopted ordinance/resolution records toCIVICCODE_INTAKE_URLwhen the suite bearer handoff value is configured - local-first Granicus, Legistar, PrimeGov, and NovusAGENDA meeting imports
- source provenance on imported meetings and agenda items
- records-ready packet export bundles with CivicCore v1.2.1 manifests, SHA256 checksums, provenance, and hash-chained audit events
- closed-session/restricted source guardrails for public packet export bundles
- safe API export-path handling through
bundle_nameunderCIVICCLERK_EXPORT_ROOT - browser QA gate covering loading, success, empty, error, and partial states
- accessibility checks for keyboard navigation, focus states, contrast, and console errors
- React staff shell QA controls covering loading, success, empty, error, and partial states for the Clerk dashboard, meeting calendar, and meeting detail workspace
- React staff shell live meeting-list wiring for dashboard metrics, calendar
cards, and meeting detail selection, with
?source=demoretained for deterministic QA state capture - React staff dashboard Meeting Runbook that turns loaded meeting, agenda, packet, notice, outcomes, minutes, and public posting records into an end-to-end ready/warning/blocked lifecycle checklist with a next-safe-action button for clerks
- React staff dashboard access panel that reads
/staff/session, shows local protected mode, open mode, OIDC browser-session mode, bearer mode, or trusted-header mode, displays signed-in subject/provider/roles when available, and links clerks or IT directly to/staff/login,/staff/logout, and/staff/auth-readiness - ADR-0009 documents why the OIDC browser session bridge remains module-local until CivicCore ships that helper, while protected API access continues to use CivicCore bearer, trusted-header, trusted-proxy-source, and optional archive bearer helpers
- nginx-served Docker/installer product routing for
/staff,/staff/...,/public, and/public/..., with workflow API calls staying under/api/...and staff auth-readiness/session contracts still proxied to the backend - React Notice Checklist Official Notice Record summary that tells clerks whether statutory public-notice proof allows the meeting to proceed, is blocked, or is incomplete, with deadline, basis, approval, posting proof, and immutable audit-hash fields visible together
- React staff dashboard meeting-body management for creating, renaming, and deactivating boards and commissions without hard-deleting meeting history
- React staff dashboard meeting scheduling for creating live calendar records from active meeting bodies, plus meeting-detail schedule editing for title, body, type, start time, and location before the legal record is locked
- API validation that rejects nonexistent or inactive meeting body ids during meeting create/update so staff cannot attach a legal meeting record to invalid ownership metadata
- React Agenda Intake workflow for submitting department agenda requests,
reviewing them as ready or needing revision, promoting ready records into
canonical agenda lifecycle work, and showing audit-hash evidence from the live
/api/agenda-intakequeue - React Notice Checklist workflow for selecting a meeting, previewing the statutory deadline, capturing notice type, posting time, statutory basis, human approval, and actor, running the live compliance check, attaching posting proof after a passing check, and showing an Official Notice Record, legal readiness proof chain, legal-blocker copy, and immutable audit-hash evidence from the live notice checklist APIs
- React Public Posting portal for resident-safe public meeting list/detail and archive search over posted agenda, posted packet, and approved minutes records, with plain-language summaries, adopted/signed minutes metadata, document downloads, public comment intake where enabled, official-record sections, missing-record guidance, and restricted-session non-disclosure copy
- React Meeting Outcomes workflow for selecting a meeting, loading captured motions/votes/action items, capturing immutable motions with seconded-by metadata, recording roll-call votes including abstentions, recusals, and absences, creating follow-up action items tied to source motions, and warning clerks that corrections are append-only rather than silent edits
- React Member Packet workflow for reviewing packet contents, item history, staff-report visibility by role, prior vote ledger entries, and member conflict/vote recording from the same workflow surface
- React Minutes Draft workflow for selecting a meeting, loading citation-gated drafts, creating drafts with explicit source material, sentence-level citations, model/prompt provenance, and human approver, and showing that AI-drafted minutes cannot be publicly posted until a human adoption workflow approves them
- React Vendor Sync workspace for registering approved vendor sources, showing healthy/degraded/circuit-open ledger state, recording run outcomes, and making the no-network safety boundary, persisted delta cursor, full reconciliation reset control, and IT fix guidance visible before scheduled vendor pulls are enabled
| README workflow claim | Verification |
|---|---|
| Public records include plain-language summaries, adopted/signed minutes metadata, agenda/packet/minutes downloads, and comment intake where enabled. | tests/test_milestone_8_public_archive.py::test_public_record_downloads_comments_and_plain_language_summary; frontend/src/App.test.tsx::shows public downloads, summaries, and comment intake where enabled |
| Public comment intake refuses disabled or closed public records with an actionable fix path. | tests/test_milestone_8_public_archive.py::test_public_comment_intake_refuses_closed_or_disabled_records_with_fix |
| Meeting outcomes capture seconded-by motion metadata and roll-call votes including recusals and absences. | tests/test_milestone_6_motion_vote_action_capture.py::test_api_captured_motion_is_immutable_and_corrections_reference_original; frontend/src/App.test.tsx::opens the member packet surface for item history, staff report visibility, and conflict recording |
| The staff workflow exposes department/legal/clerk agenda routing and audit signoff, plus member packet review for item history, staff-report visibility, and conflict recording. | frontend/src/App.test.tsx::submits and reviews agenda intake from the staff workspace; frontend/src/App.test.tsx::opens the member packet surface for item history, staff report visibility, and conflict recording |
| Meeting cancellation reaches the lifecycle audit path from the React meeting detail surface. | frontend/src/App.test.tsx::cancels a scheduled meeting through the lifecycle audit path |
| README data model claim | Verification |
|---|---|
All fourteen canonical CivicMeetings tables remain present in the shared civicclerk schema. | tests/test_milestone_2_schema_and_migrations.py::test_canonical_table_models_exist_and_no_tables_are_missing_or_extra |
civicclerk_0011_data_model upgrades, downgrades to the prior release head, and re-upgrades while preserving the packet-version contract. | tests/test_milestone_2_schema_and_migrations.py::test_alembic_command_upgrades_real_pgvector_database; tests/test_milestone_2_schema_and_migrations.py::test_data_model_completion_migration_declares_reversible_cc5_contract |
| Packet snapshots are versioned per meeting by schema constraint. | tests/test_milestone_2_schema_and_migrations.py::test_packet_versions_are_versioned_per_meeting_by_schema_contract |
| Motion and vote records carry append-only correction metadata that references the original record. | tests/test_milestone_2_schema_and_migrations.py::test_motion_vote_canonical_tables_preserve_append_only_correction_contract; tests/test_milestone_6_motion_vote_action_capture.py::test_api_captured_motion_is_immutable_and_corrections_reference_original |
| Closed-session material has staff-only ACL fields, and archive search uses released CivicCore search helpers while document-table references remain ADR-bound until CivicCore ships document tables. | tests/test_milestone_2_schema_and_migrations.py::test_closed_session_material_has_staff_only_acl_schema_contract; tests/test_milestone_2_schema_and_migrations.py::test_civiccore_document_and_search_extraction_boundary_is_documented; tests/test_milestone_8_public_archive.py::test_archive_search_requires_allowed_bearer_role_for_closed_session_visibility |
| README prompt claim | Verification |
|---|---|
Every spec-required CivicMeetings prompt ships as versioned YAML and resolves through civiccore.llm.resolve_template under consumer_app="civicclerk". | tests/test_milestone_9_prompt_yaml_evals.py::test_all_spec_prompts_are_versioned_and_resolve_through_civiccore |
| The offline eval harness covers policy phrases, public approval gates, and input mutation stability without network calls. | tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_runs_offline_with_ollama_provider_selected |
| The eval harness uses the CivicCore resolver path instead of standalone prompt rendering. | tests/test_milestone_9_prompt_yaml_evals.py::test_prompt_eval_harness_uses_civiccore_resolver_not_standalone_rendering |
- Docker Compose deployment stack with PostgreSQL 17 + pgvector, Redis 7.2,
Ollama, FastAPI, Celery worker, Celery Beat, and nginx-served React frontend
wired to the
/apiproxy path - optional scheduled local connector import sync through Celery Beat, disabled
by default, that reads approved agenda-system JSON export drops from
/data/connector-imports, writes a provenance ledger under/data/exports, and never contacts vendor networks - vendor live-sync readiness and persistence primitives that validate proposed
source URLs through CivicCore guards, reject credentials in URLs, persist
source/run/failure state in
vendor_sync_*tables, project source-list health and operator fix paths through the shared CivicCore source-status helper, computehealthy/degraded/circuit_open, and open the circuit after five consecutive full-run failures or two post-unpause grace-period failures - Docker Compose staff-auth env propagation for OIDC browser-login,
bearer-token, and trusted-header pilot profiles, so
.envvalues reach the API, worker, and beat containers consistently - unsigned Windows installer source package with Inno Setup build script,
Docker Desktop prerequisite check, Install or Repair shortcut, daily Start
shortcut,
.envcreation fromdocs/examples/docker.env.example, generated local PostgreSQL password, health checks, seeded demo startup, and an installer wizard warning that explains the expected "Unknown Publisher" / "Windows protected your PC" first-install experience, why this small free open-source project ships unsigned installers, and when it is OK to choose "More info" -> "Run anyway" - CivicMeetings v1.0.4 release gate and build artifacts
scripts/start_fresh_install_rehearsal.ps1to rehearse the documented Windows-first wheel install and first-run smoke checks from an isolated.fresh-install-rehearsalvirtual environmentscripts/start_fresh_install_rehearsal.shto rehearse the same fresh-install wheel path from Bash on Linux, macOS, or Git Bashscripts/check_backup_restore_rehearsal.pyplusscripts/start_backup_restore_rehearsal.ps1andscripts/start_backup_restore_rehearsal.shto seed the SQLite-backed workflow stores, back them up with packet export evidence, restore them to.backup-restore-rehearsal, and verify the restored records are readabledocs/examples/deployment.env.examplepluspython scripts/check_deployment_readiness.py --env-file ... --strictso IT can validate a deployment env profile without hand-exporting every variablescripts/check_protected_deployment_smoke.pyto consume a completed env profile and execute the readiness-provided protected session and write probes without printing bearer tokensscripts/check_installer_readiness.pyto verify release artifacts, checksums, and handoff bundle contents before building or handing off installer packagesscripts/check_enterprise_installer_signing.pyremains available for downstream organizations that choose to sign their own internal copy, but CivicSuite's supported public Windows path is unsignedscripts/check_connector_sync_readiness.pyto verify supported connector payload contracts and future source guards without outbound network callsscripts/run_mock_city_environment_suite.pyto run the reusable no-network City of Brookfield mock-city contract suite for Legistar, Granicus, PrimeGov, NovusAGENDA, the Brookfield Entra ID OIDC contract, and the Brookfield backup-retention/off-host policy contract, with optional--hostile-modefixtures for IdP expiry/refresh/JWKS/MFA/clock-skew/group-claim behavior, agenda-vendor rate-limit/pagination/schema-drift/partial-outage/duplicate/stale-delta cases, and backup-retention restore/manifest/legal-hold/checksum failures before module teams add their own module-specific assertionsscripts/check_vendor_live_sync_readiness.pyto preview the vendor live-sync source contract, auth method, credential placement, health status, and circuit-breaker behavior without contacting vendor systemsscripts/run_vendor_live_sync.pyto run one explicitly enabled vendor-network pull from an approved source, revalidate the URL, read credentials from a deployment secret env var, normalize returned JSON through the existing connector contract, and record the run outcome in the vendor sync ledger- optional scheduled vendor-network sync through Celery Beat, disabled by
default and gated by both
CIVICCLERK_VENDOR_NETWORK_SYNC_SCHEDULE_ENABLEDandCIVICCLERK_VENDOR_NETWORK_SYNC_ENABLED, so approved source IDs can be pulled repeatedly only after IT has configured credentials and accepted live vendor traffic - connector-specific delta request planning for supported vendor live-sync
sources, so the scheduled path has a tested "changed since" URL contract
backed by a persisted
last_success_cursor_atsource cursor that advances only after fully successful normalized vendor pulls /vendor-live-sync/sources/{id}/cursor-resetto clear or move that cursor without contacting vendors, so IT can force a full source reconciliation with an operator reason before the next controlled scheduled pull/vendor-live-sync/sourcesand/vendor-live-sync/sources/{id}/run-logto save proposed vendor sources and record run outcomes with durable operator health state; these endpoints are no-network ledgers and do not start vendor pullsscripts/run_connector_import_sync.pyto normalize one or more local connector export files into a repeatable import ledger without contacting vendor systemsCIVICCLERK_VENDOR_SYNC_DB_URLfor the durable vendor live-sync source, run-log, and failure ledger; it defaults to an in-memory local rehearsal store when unsetCIVICCLERK_CONNECTOR_SYNC_ENABLED,CIVICCLERK_CONNECTOR_SYNC_PAYLOAD_DIR_HOST,CIVICCLERK_CONNECTOR_SYNC_LEDGER_PATH,CIVICCLERK_CONNECTOR_SYNC_CONNECTORS, andCIVICCLERK_CONNECTOR_SYNC_INTERVAL_SECONDSfor optional Docker/Celery scheduled ingestion of approved local connector export dropsscripts/build_release_handoff_bundle.ps1to package the built wheel, sdist, checksums, current docs, proxy reference, and rehearsal helpers into a repeatable IT handoff zip without calling it an installer/staff/login,/staff/oidc/callback, and/staff/logoutfor the first OIDC authorization-code + PKCE browser sign-in/session foundation/staff/sessionto report whether the live staff shell is in protected default mode, local open mode, OIDC-protected staff mode, OIDC browser-session mode, bearer-protected staff mode, or trusted-header staff mode/staff/auth-readinessto report whether the current OIDC token-validation and browser-login, bearer-token, or trusted-header staff auth contract is deployment-ready- structured
session_probeandwrite_probeguidance from/staff/auth-readinesswhen OIDC, bearer, or trusted-header deployment is ready - structured
reverse_proxy_referenceguidance from/staff/auth-readinesswhen trusted-header deployment needs a real nginx bridge starting point - structured
local_proxy_rehearsalguidance from/staff/auth-readinesswhen trusted-header mode needs a safe loopback-only rehearsal path CIVICCLERK_STAFF_AUTH_MODE=protected|open|oidc|bearer|trusted_headerfor the first staff auth foundation contractCIVICCLERK_STAFF_OIDC_PROVIDER,CIVICCLERK_STAFF_OIDC_ISSUER,CIVICCLERK_STAFF_OIDC_AUDIENCE,CIVICCLERK_STAFF_OIDC_JWKS_URL,CIVICCLERK_STAFF_OIDC_ROLE_CLAIMS, andCIVICCLERK_STAFF_OIDC_ALGORITHMSfor municipal identity-provider access-token validationCIVICCLERK_STAFF_OIDC_AUTHORIZATION_URL,CIVICCLERK_STAFF_OIDC_TOKEN_URL,CIVICCLERK_STAFF_OIDC_CLIENT_ID,CIVICCLERK_STAFF_OIDC_CLIENT_SECRET,CIVICCLERK_STAFF_OIDC_REDIRECT_URI, andCIVICCLERK_STAFF_OIDC_SESSION_COOKIE_SECRETfor browser authorization-code + PKCE sign-in with a signed HttpOnly staff session cookieCIVICCLERK_STAFF_AUTH_TOKEN_ROLESfor bearer-token-to-role mapping during staff workflow accessCIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER,CIVICCLERK_STAFF_SSO_ROLES_HEADER,CIVICCLERK_STAFF_SSO_PROVIDER, andCIVICCLERK_STAFF_SSO_TRUSTED_PROXIESfor trusted reverse-proxy SSO bridge configuration
Not shipped yet:
- city-specific live endpoint enablement for CivicRecords, CivicCode, CMS, codifier, or municipal Granicus/Legistar/PrimeGov/NovusAGENDA tenants. The CivicMeetings side now distinguishes live-wire or in-process boundary validation from supplemental adversarial mock regression checks, and real credentials plus endpoint activation remain a deployment task.
A new user can inspect and run the foundation, open staff workflow screens at /staff, open the resident-facing React public portal at /public in the Docker/nginx product path, inspect the React staff workspace in frontend/, see the current staff access mode and municipal SSO session status directly on the React dashboard, use the React dashboard Meeting Runbook to see the next safe end-to-end meeting action, create and maintain meeting bodies through the React dashboard and /api/meeting-bodies, schedule meetings through the React dashboard, load live meetings into the React dashboard/calendar/detail flow through /api/meetings, edit pre-lock meeting schedule fields through the React meeting detail view and PATCH /api/meetings/{id}, submit agenda intake items into a database-backed queue from the browser, record clerk readiness review from the browser, promote ready intake work into agenda lifecycle records, create/finalize packet assembly records from the React Packet Builder, run the React Notice Checklist with statutory deadline, Official Notice Record proof summary, basis, approval, posting-proof, legal-blocker, and audit-hash visibility, inspect the React Public Posting view over resident-safe agenda, packet, minutes, and archive search records, capture immutable motions, roll-call votes, and source-linked action items from the React Meeting Outcomes workspace, create citation-gated minutes drafts with source material, sentence citations, prompt provenance, human approver, and blocked auto-posting visibility from the React Minutes workspace, inspect the React Vendor Sync workspace for source health/circuit status and no-network run logging, persist notice checklist/posting-proof records from the browser, create citation-gated minutes drafts from the browser, publish public-safe archive records from the browser, normalize local connector exports from the browser or through scheduled local Docker import drops, persist vendor sync source/run health through CIVICCLERK_VENDOR_SYNC_DB_URL, persist agenda item lifecycle records through CIVICCLERK_AGENDA_ITEM_DB_URL, persist meeting records and lifecycle audit entries through CIVICCLERK_MEETING_DB_URL, create draft agenda items and meetings through the API, and generate a records-ready packet export bundle with manifest, checksums, provenance, and audit evidence. The Docker profile is now usable as an end-to-end local product rehearsal or pilot-grade demo with seeded Brookfield data, including a PostgreSQL-native backup/restore rehearsal, OIDC staff-token validation, OIDC browser sign-in/session-cookie foundation, React sign-in/session status polish, optional scheduled local connector export-drop ingestion, and staff-visible vendor sync ledger health; production readiness is validated by adversarial no-network mock city suites for retention/off-host backup operations, municipal IdP behavior, and vendor API drift; unsigned installer warnings are the supported public Windows path for this small free open-source project. The correct next experience is:
Read this README.
Read
USER-MANUAL.md.Read
docs/roadmap/mvp-plan.md.On Windows PowerShell, create a fresh virtual environment and install the current wheel:
python -m venv .venv .\.venv\Scripts\Activate.ps1 python -m pip install --upgrade pip python -m pip install dist/civicclerk-1.0.4-py3-none-any.whl
Start the FastAPI app from the installed package:
$env:CIVICCLERK_STAFF_AUTH_MODE="protected" python -m uvicorn civicclerk.main:app --host 127.0.0.1--port 8776
Confirm the fresh-machine smoke-check path:
GET http://127.0.0.1:8776/healthmust return{"status":"ok","service":"civicclerk","version":"1.0.4","civiccore":"1.2.1"}GET http://127.0.0.1:8776/staff/auth-readinessmust reportmode: "protected"and explain that anonymous staff writes are denied until OIDC, bearer, or trusted-header deployment is configured- Open
http://127.0.0.1:8776/staffand confirm the first workflow shell loads - In the Docker product path, open
http://127.0.0.1:8080/publicand confirm the React resident public portal loads official agenda, packet, and approved-minutes sections without exposing restricted-session existence. - Use
powershell -ExecutionPolicy Bypass -File scripts/start_fresh_install_rehearsal.ps1 -PrintOnlyto print the repeatable Windows fresh-install rehearsal plan, or rerun without-PrintOnlyto create.fresh-install-rehearsal\.venv, install the release wheel, start the installed app, and run the same smoke checks automatically - Use
bash scripts/start_fresh_install_rehearsal.sh --print-onlyto print the same fresh-install rehearsal plan from Linux, macOS, or Git Bash, or rerun without--print-onlyto create.fresh-install-rehearsal/.venv, install the release wheel, start the installed app, and run the same smoke checks automatically; Linux hosts need Python 3 withvenvsupport installed first, such aspython3-venvon Debian or Ubuntu - For the Docker product path on Windows, run
powershell -ExecutionPolicy Bypass -File install.ps1from the source checkout or installed package to create.env, build/start Docker Compose, wait for/healthand the React staff app, and openhttp://127.0.0.1:8080/ - Build the unsigned Windows setup executable with
bash installer/windows/build-installer.shon a workstation with Inno Setup 6; SmartScreen will identify it as unsigned, and Docker volumes are intentionally preserved on uninstall - Expect Windows SmartScreen to show "Unknown Publisher" or "Windows protected your PC" because CivicSuite is a small free open-source project and the public installer is not signed with a paid publisher certificate. That warning is expected; choose "More info" and "Run anyway" only when the installer came from the official CivicSuite GitHub release source or your IT team built it from verified CivicSuite source.
- Use
powershell -ExecutionPolicy Bypass -File scripts/build_release_handoff_bundle.ps1 -PrintOnlyon Windows PowerShell orbash scripts/build_release_handoff_bundle.sh --print-onlyon Linux, macOS, or Git Bash to preview the release handoff bundle, or rerun without the print-only flag afterbash scripts/verify-release.shhas builtdist/artifacts - Run
python scripts/check_installer_readiness.pyafter creating the handoff bundle to verify installer input artifacts, checksums, docs, env examples, and rehearsal helpers before building or handing off the Windows setup package - Run
python scripts/check_starter_set_integration.py --umbrella-root ..\civicsuite --require-archivesfrom this repo when verifying the CivicSuite starter-set package; it checks that CivicCore installs first, CivicRecords AI and CivicMeetings are selectable, package workflow proof is required, and Linux/Windows archives exist - Run
python scripts/check_connector_sync_readiness.pybefore vendor-network live-sync design work to prove the supported local connector payload contracts and optional future URL/ODBC guard checks without making vendor network calls - Run
python scripts/run_mock_city_environment_suite.py --output mock-city-report.jsonto prove the reusable City of Brookfield vendor-interface and municipal IdP contract suite before adding module-specific integration assertions; this does not contact vendor networks or expose mock secrets - Run
python scripts/run_mock_city_environment_suite.py --hostile-mode --output mock-city-hostile-report.jsonto prove the adversarial IdP, agenda-vendor, and backup-retention fixtures remain secret-free, no-network, and actionable before live city integration work begins - Run
python scripts/check_vendor_live_sync_readiness.py --connector legistar --source-url https://vendor.example.gov/api/meetings --auth-method bearer_tokento preview the vendor source contract, credential-placement guard, health status, and circuit-breaker behavior before any scheduled vendor pull is wired - Set
CIVICCLERK_VENDOR_SYNC_DB_URL, then usePOST /vendor-live-sync/sourcesandPOST /vendor-live-sync/sources/{id}/run-logto persist proposed vendor source health and run outcomes without making vendor network calls - For a deliberately enabled one-time vendor pull, set
CIVICCLERK_VENDOR_NETWORK_SYNC_ENABLED=true, store the credential in a deployment secret env var, then runpython scripts/run_vendor_live_sync.py --source-id <id> --db-url <ledger-url> --auth-secret-env <SECRET_ENV>; the runner records success/failure in the same circuit-breaker ledger and refuses circuit-open sources - Review
delta_request_url,cursor_param,cursor_value, andcursor_advanced_atin each one-time or scheduled vendor-network sync report; failed or partial runs intentionally leave the cursor unchanged so the next run can retry without skipping records - If IT suspects a missed vendor delta or receives a vendor backfill notice,
use the Vendor Sync workspace or
POST /vendor-live-sync/sources/{id}/cursor-resetwith a clear reason to clear the cursor for full reconciliation; the reset is recorded locally as acursor_resetrun-log event and still does not contact the vendor network - For scheduled vendor-network pulls in Docker, keep
CIVICCLERK_VENDOR_NETWORK_SYNC_ENABLED=falseandCIVICCLERK_VENDOR_NETWORK_SYNC_SCHEDULE_ENABLED=falseuntil IT has approved/vendor-live-sync/sourcesrecords, then setCIVICCLERK_VENDOR_NETWORK_SYNC_SOURCE_IDS, configureCIVICCLERK_VENDOR_NETWORK_SYNC_AUTH_SECRET_ENVor per-source secret env vars, and review the per-source reports underCIVICCLERK_VENDOR_NETWORK_SYNC_REPORT_DIR - Run
python scripts/run_connector_import_sync.py --payload-dir path\to\exports --connector granicus --output connector-import-ledger.jsonwhen IT has local agenda-system export JSON files and wants a repeatable normalized import ledger without vendor network calls, or setCIVICCLERK_CONNECTOR_SYNC_ENABLED=truewithCIVICCLERK_CONNECTOR_SYNC_PAYLOAD_DIR_HOST=.\connector-importsin the Docker.envto let Celery Beat schedule the same local-first import repeatedly - Use
python scripts/check_deployment_readiness.pyto print a non-mutating deployment preflight before moving beyond local rehearsal; add--strictwhen CI or IT handoff should fail unless auth, persistent-store env vars, packet export root, release artifacts, docs, and trusted-header proxy references are deployment-ready - Copy
docs/examples/deployment.env.exampleto a private deployment profile, replace placeholders, and runpython scripts/check_deployment_readiness.py --env-file path\to\deployment.env --strictto validate OIDC/protected auth, persistent stores, packet export root, release artifacts, docs, and proxy references without printing database URLs or token values - Run
python scripts/check_protected_deployment_smoke.py --env-file path\to\deployment.envafter strict readiness passes to execute/health,/staff/auth-readiness, the protected session probe, and the protected write probe without printing bearer tokens - Run
python scripts/check_pilot_readiness.pyafterverify-release.shand the release handoff bundle to prove developer-owned pilot readiness; the report uses adversarial mock city vendor, municipal IdP, protected-auth, and backup-retention suites as supplemental regression evidence while integration release-depth claims require live-wire or in-process boundary validation instead of marking them as unbuilt product code; the developer-owned side now includes the reusable vendor-interface, municipal IdP, and backup retention/off-host mock-city contract suites - Use
powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnlyon Windows PowerShell orbash scripts/start_backup_restore_rehearsal.sh --print-onlyon Linux, macOS, or Git Bash to preview the backup/restore rehearsal; rerun without the print-only flag to seed the five persistent SQLite stores, createbackup/civicclerk-backup-manifest.json, restore into.backup-restore-rehearsal, and verify the restored agenda intake, agenda item, meeting, packet assembly, notice checklist, and packet export evidence - For the Docker product path, use
powershell -ExecutionPolicy Bypass -File scripts/start_docker_backup_restore_rehearsal.ps1 -PrintOnlyon Windows PowerShell orbash scripts/start_docker_backup_restore_rehearsal.sh --print-onlyon Linux, macOS, or Git Bash to preview a PostgreSQL-native rehearsal; rerun without the print-only flag while the Compose stack is running to create.docker-backup-restore-rehearsal, capturebackup/civicclerk-postgres.dumpwithpg_dump, restore it into a temporary database withpg_restore, writebackup/civicclerk-docker-backup-manifest.json, verify restored application tables, and drop the temporary restore database without overwriting the source database - Use
powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnlyon Windows PowerShell orbash scripts/start_protected_demo_rehearsal.sh --print-onlyon Linux, macOS, or Git Bash to print the protected trusted-header demo profile before launching it
Exercise
/agenda-intake,/agenda-intake/{id}/review,/agenda-items,/agenda-items/{id}/transitions,/meetings,/meetings/{id}/transitions,/meetings/{id}/packet-snapshots,/meetings/{id}/packet-assemblies,/packet-assemblies/{id}/finalize,/meetings/{id}/notice-checklists,/notice-checklists/{id}/posting-proof,/meetings/{id}/export-bundle,/meetings/{id}/notices/post,/meetings/{id}/motions,/motions/{id}/votes,/meetings/{id}/action-items,/meetings/{id}/minutes/drafts,/meetings/{id}/public-record,/public/meetings,/public/archive/search,/imports/{connector}/meetings,/vendor-live-sync/sources,/vendor-live-sync/sources/{id}/run-log, and/vendor-live-sync/sources/{id}/cursor-resetto smoke-check Milestone 10 plus the production-depth live staff action slices and the no-network vendor sync ledger.Set
CIVICCLERK_AGENDA_ITEM_DB_URLbefore agenda item lifecycle persistence smoke checks, setCIVICCLERK_MEETING_DB_URLbefore meeting persistence smoke checks, setCIVICCLERK_VENDOR_SYNC_DB_URLbefore durable vendor sync ledger smoke checks, and setCIVICCLERK_EXPORT_ROOTbefore API packet export smoke checks; API callers provide a relativebundle_name, not an arbitrary filesystem path.In OIDC, bearer, or trusted-header mode, call
/staff/auth-readinessfirst and use the returnedsession_probepluswrite_probebefore trusting a protected deployment. In OIDC mode, complete the browser-login settings and open/staff/login; CivicMeetings redirects to the municipal provider with authorization-code + PKCE parameters, accepts the callback at/staff/oidc/callback, and stores a signed HttpOnly CivicMeetings staff session cookie instead of storing the raw OIDC token in the browser.If trusted-header mode is headed toward a real deployment, start from the returned
reverse_proxy_referenceblock and the shippeddocs/examples/trusted-header-nginx.confsample before you wire in your real identity provider variables and TLS paths.If trusted-header mode is still being rehearsed on one workstation, use the returned
local_proxy_rehearsalblock, setCIVICCLERK_STAFF_SSO_TRUSTED_PROXIES=127.0.0.1/32, runpython scripts/local_trusted_header_proxy.py, and browse the helper listen URL instead of the upstream app URL.If you want the trusted-header demo profile without hand-exporting env vars on Windows PowerShell, run
powershell -ExecutionPolicy Bypass -File scripts/start_protected_demo_rehearsal.ps1 -PrintOnlyto print the exact commands, then rerun the same script without-PrintOnlyto launch the app on8877and the helper proxy on8878.If you want the same protected demo profile from Bash on Linux, macOS, or Git Bash, run
bash scripts/start_protected_demo_rehearsal.sh --print-onlyfirst, then rerun without--print-onlyto launch the app on8877and the helper proxy on8878.Run
CIVICCORE_LLM_PROVIDER=ollama CIVICCLERK_EVAL_OFFLINE=1 NO_NETWORK=1 python scripts/run-prompt-evals.pybefore changing prompt YAML.Run
python scripts/verify-browser-qa.pybefore landing frontend or browser-visible documentation changes.For the React staff workspace slice, run the frontend package from
frontend/withnpm ci,npm audit --audit-level=moderate,npm run dev,npm run test, andnpm run build.Follow GitHub issues and discussions for future hardening; do not label mock-only evidence as integration release depth.
CivicMeetings follows the CivicSuite pattern:
- FastAPI backend
- React frontend
- PostgreSQL 17 + pgvector
- Redis 7.2 + Celery + Celery Beat
- Ollama / Gemma 4 through
civiccore.llm, selected byCIVICCORE_LLM_PROVIDER=ollama - local data ownership, no runtime telemetry, no cloud inference
The first Docker Compose stack now exists for local product rehearsal:
Copy-Item docs\examples\docker.env.example .env
docker compose up --buildThen open http://127.0.0.1:8080/staff for the React staff app, or
http://127.0.0.1:8776/health for the API health check. The default
CIVICCLERK_STAFF_AUTH_MODE=protected is the default and denies anonymous staff writes; explicitly set CIVICCLERK_STAFF_AUTH_MODE=open only for local rehearsal, or switch to
OIDC, bearer, or trusted-header mode before shared deployment. The Compose profile
sets CIVICCLERK_DEMO_SEED=1 by default so the API starts with Brookfield
meeting bodies, meetings, promoted agenda intake, a finalized packet, a posted
notice checklist with posting proof, captured outcomes, citation-gated minutes,
and a public archive record. Set CIVICCLERK_DEMO_SEED=0 in .env for an
empty rehearsal database. The Windows installer package under
installer/windows/ wraps this same Docker stack.
The installer is unsigned, local-rehearsal oriented, and still requires Docker
Desktop; use OIDC, bearer, or trusted-header auth before any shared deployment.
The foundation is intentionally thin. Canonical schema, Alembic scaffolding, agenda item lifecycle enforcement, agenda item lifecycle persistence, meeting lifecycle enforcement, meeting records, packet snapshot versioning, packet assembly records, notice checklist records, shared notice compliance enforcement, immutable motion capture, immutable vote capture, action-item capture, citation-gated minutes draft capture, permission-aware public archive endpoints, prompt YAML/evaluation gates, local-first connector import normalization, browser QA gates, CivicMeetings v1.0.4 release artifacts, and CivicCore v1.2.1 packet export, browser-evidence verification, connector runtime validation, and trusted-header config enforcement primitives are present. Minutes drafts require sentence-level citations, YAML prompt-version provenance, and human approval before acceptance, and they are never auto-adopted or auto-posted. Anonymous public archive endpoints do not reveal closed-session content in response bodies, counts, suggestions, or error messages. Connector imports record source provenance and do not require outbound network calls in the default local profile. The vendor live-sync foundation now validates proposed vendor source URLs without network calls, blocks credentials in URLs, persists source/run/failure state in vendor_sync_sources, vendor_sync_run_log, and vendor_sync_failures, computes source health as healthy, degraded, or circuit_open, persists last_success_cursor_at, plans connector-specific delta URLs from that cursor, advances it only after fully successful normalized pulls, and follows the CivicRecords AI circuit-breaker pattern of five consecutive full-run failures or two grace-period failures after unpause. Public packet exports block closed-session/restricted sources and include manifest, checksum, provenance, and audit evidence. Agenda item records now persist lifecycle status and CivicCore-verifiable transition audit hashes when CIVICCLERK_AGENDA_ITEM_DB_URL is configured, and ready agenda intake records can be promoted into those lifecycle records while preserving the generated agenda item id, promotion timestamp, and audit hash on the intake record. Meeting records now persist scheduled starts, meeting body ids, locations, normalized meeting type, lifecycle status, and CivicCore-verifiable transition and schedule-edit audit hashes when CIVICCLERK_MEETING_DB_URL is configured; schedule edits are allowed before the in-session lock point, write audit entries, and validate changed meeting body ids before accepting create/update requests. Vendor sync source, run, failure, and cursor state persist when CIVICCLERK_VENDOR_SYNC_DB_URL is configured; the API records operator state and no-network cursor resets without pulling vendors, while scripts/run_vendor_live_sync.py provides an explicitly enabled one-source pull runner that records outcomes in the same circuit-breaker ledger. Packet assembly records now persist source references, citations, linked packet snapshot ids, and durable audit hashes. Notice checklist records persist compliance outcomes, warnings, posting proof, and durable audit hashes. Browser QA now checks loading, success, empty, error, and partial states plus keyboard, focus, contrast, and console evidence, and release screenshots are bound to the current docs page through shared CivicCore verification helpers. CivicMeetings v1.0.4 now pairs with the published civiccore 1.2.1 wheel from the v1.2.1 release asset. The first staff auth foundation is now explicit: fresh installs default to CIVICCLERK_STAFF_AUTH_MODE=protected so anonymous staff writes are denied, local rehearsals can explicitly opt into CIVICCLERK_STAFF_AUTH_MODE=open, municipal identity-provider deployments can set CIVICCLERK_STAFF_AUTH_MODE=oidc plus issuer, audience, JWKS, role-claim, algorithm, authorization URL, token URL, client, redirect URI, and session-cookie-secret settings, bearer-protected pilots can set CIVICCLERK_STAFF_AUTH_MODE=bearer plus CIVICCLERK_STAFF_AUTH_TOKEN_ROLES, and trusted reverse-proxy deployments can set CIVICCLERK_STAFF_AUTH_MODE=trusted_header plus CIVICCLERK_STAFF_SSO_PRINCIPAL_HEADER, CIVICCLERK_STAFF_SSO_ROLES_HEADER, CIVICCLERK_STAFF_SSO_PROVIDER, and CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES. The /staff/auth-readiness endpoint now tells operators whether those OIDC token-validation, OIDC browser-login, bearer, or trusted-proxy settings are merely present or actually deployment-ready, and it includes a loopback-only rehearsal recipe so trusted-header testing does not require inventing a custom proxy first.
The staff experience at /staff now includes a product cockpit plus first workflow screens for agenda intake, packet assembly/export, notice checklist/posting-proof, meeting outcome, minutes draft, public archive, connector import, and vendor sync work. It is intentionally honest: the cockpit gives clerks a day-at-a-glance desk, reads the live agenda intake queue for ready/pending/needs-revision counts, the Agenda Intake, Packet Assembly, Notice Checklist, Meeting Outcomes, Minutes Draft, and Vendor Sync panels render live queue/record rows with escaped user-submitted titles where applicable and actionable empty/unavailable-store rows, the workflow screens can submit their corresponding live API actions, the auth panel now renders concrete protected-session and protected-write probes from /staff/auth-readiness when OIDC, bearer, or trusted-header mode is ready, it surfaces the loopback-only local proxy rehearsal command and env vars when trusted-header mode is being staged, and the broader multi-role React clerk console is now beginning under frontend/. The React slice uses the CivicSuite mockup direction for a real staff shell, meeting body management, meeting scheduling, meeting calendar, lifecycle ribbon, audit/evidence drawer, pre-lock schedule editing, Agenda Intake submit/review/promotion, Packet Builder promoted-item selection, packet draft creation, per-meeting queue review, packet finalization, Notice Checklist statutory deadline review, legal-blocker copy, posting-proof attachment, immutable audit-hash evidence, Public Posting resident-safe list/detail/search, Meeting Outcomes motion/vote/action capture with immutable-record guidance, Minutes Draft source/citation/provenance capture, Vendor Sync source-health/circuit-breaker/cursor visibility with no-network run logging and full-reconciliation reset guidance, and no-dead-end QA states. The Docker profile now seeds Brookfield demo data so city IT can open the React app and see live work immediately; the unsigned Windows installer wraps that same stack for install/repair and daily start. The resident-facing /public route in the nginx product path now opens the React public portal directly, loads public calendar records, public-safe detail, and anonymous archive search from the live public APIs, and keeps restricted-session existence, counts, and summaries out of resident copy.
For Windows installer packaging, install.ps1 is the install/repair entrypoint and installer/windows/ contains the Inno Setup source, launcher scripts, prerequisite checker, and build helper. The package creates .env from docs/examples/docker.env.example when needed, generates a local database password, starts Docker Compose with seeded demo data by default, waits for API and staff-app health, and opens the React staff app. The public CivicSuite installer is unsigned by design for this small free open-source project, so Windows may show SmartScreen or Unknown Publisher warnings; it is OK to bypass those warnings only for official CivicSuite release artifacts or installer builds your IT team produced from verified CivicSuite source. The installer preserves Docker volumes on uninstall and does not replace the protected-auth deployment checks required for shared municipal use.
For the first real trusted-header deployment handoff, docs/examples/trusted-header-nginx.conf now ships a reference nginx bridge that strips client-supplied identity headers, sets proxy-owned staff headers, and points operators back to CIVICCLERK_STAFF_SSO_TRUSTED_PROXIES plus the /staff/auth-readiness contract before live staff traffic is trusted.
For fresh Windows install rehearsals, scripts/start_fresh_install_rehearsal.ps1 now prints and can execute the documented wheel-install path from an isolated .fresh-install-rehearsal virtual environment: create venv, upgrade pip, install dist/civicclerk-1.0.4-py3-none-any.whl, set CIVICCLERK_STAFF_AUTH_MODE=protected, launch the installed app on 127.0.0.1:8776, verify /health, verify /staff/auth-readiness, and fetch /staff. If the wheel is missing, the helper tells the operator to build it with python -m build before trying again.
For fresh Bash install rehearsals on Linux, macOS, or Git Bash, scripts/start_fresh_install_rehearsal.sh now prints and can execute the same wheel-install path from an isolated .fresh-install-rehearsal/.venv, with the same /health, /staff/auth-readiness, /staff, missing-wheel, occupied-port, and Python venv prerequisite checks as the Windows helper. On Debian or Ubuntu, install python3-venv before executing the helper.
For IT release handoff, scripts/build_release_handoff_bundle.ps1 and scripts/build_release_handoff_bundle.sh now print and can create dist/civicclerk-1.0.4-release-handoff.zip containing the built wheel, source distribution, checksums, current README/manual/changelog/license, docs landing page, deployment env profile example, installer-readiness helper, enterprise signing-readiness helper, connector sync readiness helper, vendor live-sync readiness helper, protected deployment smoke helper, trusted-header nginx reference, and the fresh-install/protected-demo rehearsal helpers. Both helpers intentionally refuse to overwrite an existing bundle and they are release-input zips, not setup executables; build artifacts first with bash scripts/verify-release.sh. After the zip exists, python scripts/check_installer_readiness.py verifies the handoff bundle before the Windows setup package is built or handed to IT.
For connector import operations, python scripts/check_connector_sync_readiness.py verifies the supported Granicus, Legistar, PrimeGov, and NovusAGENDA local payload contracts without outbound network calls. It can also validate a proposed --source-url or --odbc-connection-string through the shared CivicCore host guards before vendor-network live sync is designed. python scripts/check_vendor_live_sync_readiness.py --connector legistar --source-url https://vendor.example.gov/api/meetings --auth-method bearer_token checks the first live-sync source contract, rejects credentials in URLs, previews healthy/degraded/circuit_open, and simulates the circuit breaker without contacting the vendor. With CIVICCLERK_VENDOR_SYNC_DB_URL set, POST /vendor-live-sync/sources saves a validated source and POST /vendor-live-sync/sources/{id}/run-log records success, partial, or failed run outcomes into the durable no-network ledger; GET /vendor-live-sync/sources and GET /vendor-live-sync/sources/{id}/run-log expose the operator health state and actionable fix text. When IT has exported local JSON files, python scripts/run_connector_import_sync.py --payload-dir path\to\exports --output connector-import-ledger.json normalizes <connector>.json or <connector>/*.json payloads through the same import contract and writes a provenance ledger. In the Docker product path, IT can enable the same local-first normalization on a schedule with CIVICCLERK_CONNECTOR_SYNC_ENABLED=true, drop approved exports into CIVICCLERK_CONNECTOR_SYNC_PAYLOAD_DIR_HOST, and review the ledger at CIVICCLERK_CONNECTOR_SYNC_LEDGER_PATH. This scheduled local export-drop sync still does not contact vendors, and the vendor live-sync ledger does not contact vendors until a later adapter/scheduled-pull slice is built.
For deployment hardening, scripts/check_deployment_readiness.py now prints a non-mutating readiness report that reuses the staff auth readiness contract, checks whether deployment database URL environment variables are present without printing secret values, warns when CIVICCLERK_EXPORT_ROOT is still using the local default, verifies release artifacts and required docs exist, and confirms the trusted-header nginx reference is available. Run it without flags for an operator report, with --env-file path\to\deployment.env to validate a copied profile from docs/examples/deployment.env.example, or with --strict when CI or IT handoff should fail unless the deployment posture is ready.
CivicMeetings emits ordinance/resolution handoff records to CivicCode when the
city-core installer or operator configures CIVICCODE_INTAKE_URL and the suite
bearer handoff value. On successful
POST /meetings/{meeting_id}/ordinance-resolution-handoff, CivicMeetings maps the
meeting, motion/agenda provenance, affected sections, source document reference,
and adopted text into CivicCode's existing
/api/v1/civiccode/staff/civicclerk/ordinance-events intake contract. The
local handoff record always shows the result:
EMIT_DELIVEREDwithciviccode_event_idwhen CivicCode accepts it.EMIT_FAILEDwithciviccode_handoff_last_errorandciviccode_handoff_last_attempt_atwhen CivicCode returns 4xx/5xx or the network times out.EMIT_SKIPPED_UNCONFIGUREDwhen either required setting is missing.
Retry failed or previously unconfigured records with
POST /meetings/{meeting_id}/ordinance-resolution-handoff/retry. CivicMeetings does
not run an infinite background retry loop; operators should fix the URL, shared
value, or CivicCode health issue shown in the local record and then retry.
For protected deployment smoke checks, scripts/check_protected_deployment_smoke.py --env-file path\to\deployment.env now loads the completed env profile, requires strict deployment readiness, verifies /health and /staff/auth-readiness, executes the readiness-provided protected session probe, executes the protected write probe, and redacts bearer tokens from output. Trusted-header profiles use 127.0.0.1 as the default in-process proxy source; pass --trusted-proxy-client-ip when the completed profile allowlists a different proxy test address. The sample profile intentionally fails this smoke until placeholders are replaced.
For local wheel backup/restore rehearsal, scripts/check_backup_restore_rehearsal.py creates a timestamped run under .backup-restore-rehearsal, seeds the SQLite-backed agenda intake, agenda item, meeting, packet assembly, and notice checklist stores, writes packet export evidence, copies those files into a backup directory with civicclerk-backup-manifest.json, restores them to separate restored-data and restored-exports directories, and reopens the restored records through CivicMeetings repositories. Operators can preview the Windows-first wrapper with powershell -ExecutionPolicy Bypass -File scripts/start_backup_restore_rehearsal.ps1 -PrintOnly or the Bash wrapper with bash scripts/start_backup_restore_rehearsal.sh --print-only; failures name the file or record that did not survive and tell the operator to keep the run directory, fix the backup source or env var, and rerun with a new run id.
For Docker/PostgreSQL backup/restore rehearsal, scripts/check_docker_backup_restore_rehearsal.py works against the running Compose stack instead of the SQLite wheel stores. Operators can preview it with powershell -ExecutionPolicy Bypass -File scripts/start_docker_backup_restore_rehearsal.ps1 -PrintOnly or bash scripts/start_docker_backup_restore_rehearsal.sh --print-only; rerunning without the print-only flag creates .docker-backup-restore-rehearsal, uses pg_dump to write backup/civicclerk-postgres.dump, creates a temporary restore database, runs pg_restore, records restored application tables in restore-verification.json, writes backup/civicclerk-docker-backup-manifest.json, and drops the temporary restore database by default. It does not drop, clean, or overwrite the source civicclerk database.
For protected demos on Windows PowerShell, scripts/start_protected_demo_rehearsal.ps1 now prints and can launch the loopback-only trusted-header profile end to end: the app on 127.0.0.1:8877, the helper proxy on 127.0.0.1:8878, the required trusted-header env vars, the health/readiness checks, and the browser target for /staff.
For Bash-based operator rehearsals on Linux, macOS, or Git Bash, scripts/start_protected_demo_rehearsal.sh now prints and can launch the same loopback-only trusted-header profile with export commands and the same smoke-check/browser targets instead of leaving Unix shell parity undocumented.
Before every push:
python -m pytest
bash scripts/verify-docs.sh
python scripts/check-civiccore-placeholder-imports.py
python scripts/verify-browser-qa.py
CIVICCORE_LLM_PROVIDER=ollama CIVICCLERK_EVAL_OFFLINE=1 NO_NETWORK=1 python scripts/run-prompt-evals.py
bash scripts/verify-release.shCode: Apache License 2.0; see LICENSE-CODE.
Documentation: CC BY 4.0 unless otherwise stated; see LICENSE-DOCS.