Status: 2026-08-21. This describes the executable repository and public demo, not a production deployment or a compliance assessment.
The public static site has no accounts, uploads, telemetry, applicant-data store, parcel connection, or permitting-system integration, and makes no model call on its own. ADR 0004 directs a separate optional AI service; its data flow is recorded in "Optional runtime AI service path" below. The applicant routing form keeps submitted facts only in current page memory. The route-to-packet link contains only a public journey ID and version; it carries no project facts. The packet-presence page uses a committed synthetic record and does not accept applicant input.
The Python reference server can receive a form submission to render one response, but it does not persist that submission. A production deployment would require a separate data inventory, purpose and authority analysis, access controls, retention and deletion rules, public-records workflow, security review, and jurisdiction approval.
ADR 0002 proposes retaining the no-application-storage boundary for a first limited beta. The proposal, runbook, and portable control ledger are machine-testable planning artifacts; they do not represent a beta deployment, host review, rehearsal, approval, or partner decision.
Public static HTML/CSS/JS + committed public/synthetic data
|
v
Selected HTTPS host, DNS, and optional CDN
| deployment provider/request-metadata/subprocessor review: not_run
v
Applicant browser
|
+--> exact structured facts held in current page memory
| purpose: deterministic candidate guidance, source status,
| unresolved questions, and temporary print-oriented outputs
| application network submission: none
| cookie/local/session storage: none
|
+--> static repository data requests; no applicant answers attached
|
+--> optional official-source links cross into the linked site's boundary
|
+--> optional Browser Print / Save as PDF
user-controlled local artifact; no app retrieval/deletion path
Application service applicant record store: none
Application telemetry/runtime external model/writeback: none
Separate operational systems may create records:
repository/release + host/security + support + incident + partner review
|
+--> deployment-specific access/retention/deletion: not_run
+--> CPRA search/export and legal-hold routing: not_run
+--> privacy/security/records/partner approvals: not_run
The service-collected applicant field and purpose inventories are both empty.
The browser-memory inventory is exact and limited to the structured names
validated in data/validation/beta-operations-readiness.json: project type,
recognized jurisdiction name/slug, the encoded ADU/JADU/SB 9 screening facts,
and the bounded synthetic-journey applicability answer. The packet page
accepts no applicant field or document; it replays committed synthetic data.
Adding an address, APN, contact, permit number, upload, free text, identity,
persistence, telemetry, runtime network/model request, or writeback changes
this flow and requires a new ADR and approvals before implementation.
“No storage” means no application-managed applicant record and no applicant-answer submission. It is not a claim that the network or host has no logs. The selected static host, DNS/CDN, linked official sites, repository, support system, incident system, and partner-controlled evaluation materials may process request or operational metadata under separate terms. Their actual fields, purposes, access, subprocessors, location, retention, deletion, export, and offboarding boundary remain unknown until deployment review.
src/permit_pathways/beta_operations.py accepts only the fixed
prepared_not_approved planning state: 17 exact controls are prepared, while
all nine role approvals, future-beta deployment identifiers, host/subprocessor
details, records rehearsals, decisions, and execution receipts remain
null/not_run. It validates that pending contract; it does not inspect a host,
execute the runbook, approve a system, or establish CPRA, Information
Practices Act, SAM, or SIMM compliance. A later execution or approval record
requires a separately reviewed schema.
The role-based operational procedure in docs/BETA-OPERATIONS-RUNBOOK.md
keeps retention/deletion, CPRA routing, incident triage, support, release,
rollback, and escalation explicit. It also states that a records owner—not the
application—must search authorized repository, deployment, source/review,
support, and incident systems. The absence of an application applicant store
must not be converted into a legal conclusion that no responsive record
exists.
Portable California jurisdiction registry
+ bounded statewide/local rule records
+ dated public HCD Housing Accountability Unit history
|
v
Strict coverage-index builder in jurisdictions.py
|
v
data/jurisdictions/generated/coverage-index.json
|
v
Static bundle key: coverage_index
|
v
Recognized jurisdiction selection in check.html
|
+--> bounded statewide candidate-rule inventory
+--> limited local-layer status or not encoded
+--> dated linked HCD-history reference or no linked record in snapshot
+--> local-onboarding checklist
The builder joins committed repository inputs; neither it nor the browser
scrapes a jurisdiction site, calls an HCD service, retrieves a parcel, or
stores an applicant selection. A profile's statewide inventory is the same
bounded ADU/JADU/SB 9 candidate-rule set already screenable for every registry
entry. Its local status says only what the repository encodes: not encoded
does not mean a jurisdiction has no requirements, and a limited record is not
a complete code, forms set, fee schedule, checklist, or project finding.
Coverage-index schema version 1 deliberately contains only the 17 statewide
rule IDs, each registry slug's local_rule_ids and hcd_record_count, and
the HCD dataset's source/date/count metadata. It does not duplicate,
classify, or interpret HCD rows; the linked public correspondence remains in
data/jurisdictions/hcd-letters.json. The build rejects a local rule scope
that has no registry entry, an HCD slug that has no registry entry, or a
declared HCD total that does not match the contained rows.
HCD correspondence in a profile is a date-stamped reference from the committed public dataset. It may include inquiries, technical assistance, findings, or other correspondence, but it cannot establish the current ordinance, a compliance status, a permit outcome, or what applies to a project. Likewise, the absence of a linked record in the snapshot does not prove no HCD activity, compliance, or complete data coverage. The local-onboarding checklist identifies the evidence a maintainer should assemble before a deeper layer can exist: operative provisions/effective dates; current forms, checklist, fees, and process pages; official URLs, source-check dates, and content fingerprints; project/parcel scope, exceptions, and unresolved questions; and a named review owner/re-verification cadence. A URL by itself cannot create a local rule.
19 watched source records with retained digest/date
|
v
Scheduled or local watcher re-fetch
|
+--> unchanged: observed digest equals recorded digest
+--> changed: fetched digest differs
+--> unverifiable: fetch failed; no change inference
|
v
Proposed JSON receipt + exact run URL/commit
|
+--> scheduled workflow retains artifact for 30 days
+--> receipt with changed source IDs derives exact worklist + blank
| decision template and retains the three-file package for 30 days
+--> optional release-receipt preparation binds that exact source-state,
| worklist, and decision-ledger fingerprint; every stage remains not_run
+--> stale-only or Golden-regression-only run opens an issue without a
| misleading source-change package
+--> automation never edits the public snapshot
|
v
Deliberate repository adoption as data/source-status/current.json
|
v
Strict loader re-binds source registry and re-derives
affected/unaffected rule and Golden-case IDs; Golden fixtures use explicit
rule dependencies for positive, negative, and ambiguous cases
|
v
Generated static bundle: historical records, current overlay, rule-review
coverage, program availability, and the separate coverage index
|
+--> changed dependency: stale exact rule/output or block bound handoff
+--> unverifiable dependency: visible warning, no automatic staleness
+--> unrelated dependency: explicit unaffected control remains available
The receipt status reviewed means a repository maintainer deliberately
selected a completed-run receipt for publication. It does not record a named
human reviewer or imply legal, jurisdiction, counsel, or substantive content
approval. src/permit_pathways/source_state.py requires one observation per
watched source, binds the current data/sources.json digest, checks the exact
run receipt fields, and re-derives direct rule/Golden impact. The scheduled
workflow emits only proposed artifacts. When that workflow reports review
needed, src/permit_pathways/review_queue.py also derives a portable worklist
and blank decision template. The worklist reaches exact changed source, rule,
Golden, readiness requirement, source-backed field, linked remedy, packet, and
configured journey nodes from explicit IDs and fingerprints; an unverifiable
source creates none. New-law discovery, automatic adoption/publication,
authorized owner selection, filled dispositions, and approval remain outside
the automated flow. src/permit_pathways/source_release.py adds strict,
read-only evidence contracts for those later boundaries: a completed approval
requires every exact work item to have a resolved evidence-bound disposition;
publication then binds that exact approval and a separately validated
reviewed publication source-state snapshot; rollback binds that exact
publication and a separately validated restored snapshot. The validator
derives whether the target hold remains from those supplied source-state
records. It does not edit current.json, adopt state, run Git, deploy, or
restore anything. It also does not authenticate Git objects, reviewer
authority, a live deployment, or opaque external receipt IDs. The committed
receipt templates keep every evidence field null and remain not_run, so no
rehearsal or human action is recorded.
The source-state record is an overlay. It does not rewrite the historical rule, Golden, journey, readiness, or evidence-manifest records. The browser derives the Woodland route/checklist/parcel effects from those records' existing source bindings.
Rule record + citation + explicit source dependencies
|
v
Schema-v2 rule-verification entry
|
+--> machine_linked: no promotion claim
|
+--> promoted claim requires named review metadata,
exact citation fingerprint, and exact full-rule fingerprint
|
v
Effective-status evaluation
|
+--> fingerprint drift: demote to machine_linked
+--> changed source dependency: demote to machine_linked
+--> source age or review age: demote to machine_linked
+--> all bindings current: retain recorded effective level
|
v
Harness summary + bundle-format-6 evidence-page disclosure
data/validation/rule-verification.json cannot change deterministic rule
matching. It describes only the strength of the review claim in force.
src/permit_pathways/rule_verification.py binds any promotion to both the
normalized citation and full normalized rule record, then applies source-change,
source-age, and review-age demotion. The harness phrase
automated source/regression checks: pass reports bounded automation only.
The public evidence page exposes the current effective counts: all 19 rules
are machine_linked, with zero named human reviews and zero jurisdiction
approvals.
Official City checklist (source checked 2026-07-29)
+ public parcel-layer metadata retained
|
v
Source registry entry with URL, check date, and digest
|
+--> 25-item workflow mapping, AI-assisted and review-pending
|
+--> Plain-language action sidecar, AI-assisted and review-pending
|
+--> Made-up project facts and explicit packet inventory
|
+--> Two fabricated parcel values bound to exact metadata fields
|
v
Deterministic Python evaluator
|
+--> Per-item findings and staff questions
|
+--> Source, workflow, requirement, and packet fingerprints
|
+--> Generated evidence manifest -------------------------+
|
Golden Woodland routing fixture + candidate rule current on recorded date --+
|
v
Versioned journey resolver
|
+--> Exact scope, applicability, and reference checks
|
+--> Route, fact-envelope, workflow, packet, and journey fingerprints
|
+--> Generated synthetic journey envelope
|
v
Static build bundle
|
+--> Includes strict repository-adopted source-state overlay
+--> Includes strict rule-verification ledger
+--> Includes strict, date-bound program-availability record <---------+
| |
| Official Woodland program page checked 2026-08-09 |
| | |
| +--> “Preapproved ADU List: Coming soon!” |
| | |
| +--> plans_not_listed / future-state boundary --+
|
v
Browser validates the journey, linked route/readiness evidence,
fingerprints, current source-review windows, exact changed-source bindings,
and program availability
|
+--> Missing, malformed, or expired availability record: hold
|
+--> Current availability record + active, unedited canonical sample
+ explicit Yes
| |
| +--> prepare.html?journey=<public-id>&version=<version>
| |
| +--> Exact valid simulation entry: render generated result
| | |
| | +--> Derive print-focused journey summary
| | |
| | +--> Browser Print / Save as PDF
| | (no app-side export or storage)
| +--> Direct, malformed, mismatched, stale, or
| availability-blocked: hold
| findings and print summary
|
+--> Edited/different sample, No, or I'm not sure: no packet link
This path exposes a source-bound future-state simulation, not a currently usable City preapproved plan or applicant-ready workflow. A current availability record authorizes only display of that bounded simulation; it cannot create a screening match, make the readiness workflow applicable, or establish that a plan exists.
The City of Woodland checklist is a public source retained at
corpus/woodland/preapproved-adu-permit-checklist.pdf. Its official URL,
source-check date of 2026-07-29, and digest are recorded in
data/sources.json; the document is not described as inherently dated.
The Yolo County public parcel feature-layer metadata is retained at
corpus/yolo/public-parcels-layer.json with the same URL/date/digest controls.
The latter describes available fields; it is not a downloaded parcel record.
Source retrieval and source-watcher execution are repository maintenance
operations, not browser requests made on behalf of an applicant.
Program availability is separate from the checklist. The official
Woodland Preapproved ADU Plan Program page
was checked 2026-08-09 and says “Preapproved ADU List: Coming soon!” That
manual, date-bound observation is recorded in
data/availability/woodland-preapproved-adu-program.json with its excerpt
fingerprint and recheck deadline. It is not inferred from the checklist and is
not represented as a watched-source proof that a plan is available.
data/workflows/registry.jsondeclares the repository-relative workflow, packet, remedy, journey, availability-policy, and generated-output paths. Every canonical input is raw-byte pinned. The strict Python loader rejects duplicate JSON keys, non-finite or oversized records, symlinks/hard links, cross-platform-unsafe names, duplicate or orphan IDs/files, shared paths, traversal, wrong-directory paths, fingerprint drift, and IDs that disagree with their referenced records. It currently contains one prototype entry and selects that same Woodland entry as the browser default; a synthetic two-entry test does not represent multiple active workflows.data/availability/woodland-preapproved-adu-program.jsoncontains the official program-page binding,plans_not_listedstatus, future-state simulation boundary, and manual recheck deadline. Its strict schema is isolated from rule matching and readiness evaluation.data/readiness/workflows/woodland-preapproved-detached-adu.jsoncontains the bounded workflow, nine tri-state facts, 25 requirements, source locators, excerpts, conditions, and bindings to the recorded checklist and parcel-layer metadata. Two fact definitions name exact parcel-layer fields.data/readiness/samples/woodland-preapproved-adu.jsoncontains one labeled synthetic packet. Seven facts are markedsynthetic_applicant_assertion; two concrete fabricated values usesynthetic_public_record_fixtureand carry the exact source ID, field, and recorded date. Every requirement has an explicit inventory status.data/readiness/remedies/woodland-preapproved-detached-adu.jsoncontains versioned AI-assisted action drafts. The current status isprototype_review_pending, with no reviewer or completed-review claim.
The sample contains no real applicant, address, assessor parcel number, permit number, contact information, plan, or application file.
data/journeys/woodland-preapproved-detached-adu.json is a reference-only,
versioned definition for one synthetic journey. It names the existing golden
screening case, one candidate-route rule, the readiness workflow and packet,
and designates one applicability fact as applicant-editable. It does not
duplicate the intake, rule, workflow, packet, or evaluator output.
src/permit_pathways/journey.py resolves those references at build time. It
requires the candidate route to match the complete golden case and to be
inside its source-review window on the sample's recorded evaluation date,
requires the screening and readiness scopes to agree, and requires the
canonical readiness applicability status to be applies. It emits the
resolved route evidence with that as-of date and review deadline, the shared
synthetic fact envelope with per-fact provenance, applicability facts, the
full readiness evidence manifest, and fingerprints for the route, screening
case, fact envelope, workflow, packet, and complete journey. A mismatch stops
generation. Browser code must still compare the recorded review deadlines
with the current date before presenting an affirmative handoff. It does so at
runtime together with the route, readiness, fact-envelope, and journey
fingerprint checks described below.
The journey resolver does not use program availability to manufacture a route
or readiness result. src/permit_pathways/program_availability.py validates
that independent record at build time, and browser entry validation enforces
its recheck date. Missing, malformed, or expired program evidence blocks the
future-state display even when the synthetic journey itself remains internally
consistent.
src/permit_pathways/readiness.py loads and strictly validates the workflow,
packet, source binding, and remedy metadata. The evaluator compares explicit
facts and inventory statuses. Source-shaped parcel fixtures must match the
workflow's source ID, field name, and recorded date and cannot be used in a
packet labeled non-synthetic. The evaluator does not import the remedy
sidecar, call a model, inspect files, retrieve a parcel, or infer missing
facts.
Unknown conditions remain staff questions. A changed or stale source prevents
the evaluator from publishing a favorable packet summary. The result uses
no_known_gaps_in_bounded_manifest when every applicable item is reported
present; it never calls the packet complete.
src/permit_pathways/readiness_cli.py selects a registry entry by stable
workflow ID and prints the evidence manifest to standard output. Its legacy
path options are exact assertions against that entry, not an unregistered path
bypass. It checks source currency against the current UTC date unless a person
explicitly requests a historical --as-of replay. The CLI itself does not
store the result. A person who redirects that output creates a local file
outside the CLI's storage behavior. review_queue_cli.py builds contexts for
every registered workflow by default and can narrow to one registered ID; it
cannot infer or activate an unregistered workflow. source_release_cli.py
uses the same context loader but always binds every registered workflow; it
cannot create a repository-wide release receipt from a single selected entry.
src/permit_pathways/jurisdictions.py validates the registry shape, scoped
rules, and HCD-history input while building
data/jurisdictions/generated/coverage-index.json. The result is a portable
read-only index, not a source of deterministic matching logic. The static
builder embeds it under coverage_index; check.html only renders a profile
when the currently selected jurisdiction resolves to that registry index.
Changing or clearing the selection hides the profile. No profile data is
included in the route-to-packet URL.
scripts/build_demo_bundle.py loads and validates every registry entry, then
runs the Python evaluator against each configured canonical synthetic sample.
It writes each derived evidence record to that entry's registered output path;
for the current sole entry this is
data/readiness/generated/woodland-preapproved-adu-evidence.json and embeds
the same readiness payload in data/demo-data.js. The build also resolves each
registered journey definition; for the current entry it writes
data/journeys/generated/woodland-preapproved-detached-adu.json, and embeds
that same envelope in the bundle. Under the bundle-format-6 browser contract,
only the explicit browser_default_workflow_id is aliased to the
singular readiness object, program-availability object, and one-element
journey array. Registration alone does not expose another browser workflow.
The build also strictly loads the repository-adopted
data/source-status/current.json, requires its publication receipt to be
reviewed, re-derives its dependency impacts, and embeds it as a separate
overlay. The build strictly loads schema-v2 rule-verification data and the
date-bound Woodland program-availability record as separate inputs. Bundle
format 6 exposes those claims, the strict workflow registry, its exact raw
text, and the separate jurisdiction-coverage index. The generated-input
manifest binds the raw registry and every registered canonical input.
assets/demo.js first hashes the embedded raw registry against the bundle
receipt, confirms its parsed form matches the embedded registry object, then
validates exact shape, stable IDs, unique portable paths, availability policy,
and every registered input fingerprint. The browser cannot enumerate the
repository, so orphan-file detection belongs to the Python loader/build.
It derives the availability and generated-evidence paths from the one browser
default and verifies that the readiness, packet, journey, availability, and
jurisdiction IDs agree. Invalid registry data fails closed; an invalid
workflow-specific artifact continues to withhold only its deeper surface when
the base screening data remains valid.
check.html consumes the journey envelope only for the active, unedited
sample=adu fixture after the normal deterministic screening result exactly
matches the bound golden case and candidate route. assets/demo.js checks the
journey schema and identity; the linked golden intake, route, and readiness
records; the shared applicability provenance; every recorded fingerprint; and
the route and readiness source-review windows against the current date. It
also overlays the adopted changed-source IDs and validates the separate
program-availability schema and recheck deadline. A changed candidate-route
source blocks the handoff; a changed checklist or parcel-metadata source
blocks the packet; unrelated changes do not. A missing, malformed, or expired
availability record independently blocks the future-state handoff. An
unverifiable fetch is not included in the changed set and therefore does not
create unsupported staleness. The remaining editable applicability fact has
no default. Yes exposes the packet simulation link only after these
checks; No withholds it as not applicable; and I'm not sure withholds
it and shows the exact staff question. Yes does not establish that a City
plan is available.
The handoff URL has exactly two fields: the public journey ID and its
version. It does not move project facts from check.html to prepare.html
or claim authorization. prepare.html validates those two fields and repeats
the journey, source-currency, and availability checks. A missing, duplicated,
extra, malformed, mismatched, stale, or expired-availability entry withholds
the packet cover and findings. A valid simulation entry renders the
Python-generated result; JavaScript does not recalculate packet findings.
Only after that same exact entry, integrity, source-currency, and availability
path succeeds, the browser
derives a print-focused summary from the normalized journey and readiness
objects already in memory. It includes the candidate route, labeled synthetic
facts, the three reported-missing preparation actions, direct staff questions,
route/checklist/parcel-metadata evidence, boundary text, and the journey
ID/version. The action block preserves its AI-assisted, review-pending, and
not-human-reviewed status. It does not fetch new data or recalculate either the
route or packet result. The print button invokes window.print(); the browser, not the
application, controls printing or Save as PDF. Print media hides the remaining
site and detailed packet surfaces. Invalid, direct, or availability-blocked
entry never reveals this summary.
The browser does not send the synthetic facts to a server or model. It does not use local storage, session storage, cookies, or an upload control. A user may choose to follow the official checklist or parcel-metadata link. The handoff is therefore replay of one public made-up future-state record, not continuity for a real applicant case or a currently usable City plan. Choosing browser Print or Save as PDF can create a user-controlled artifact outside the app; the app does not create, name, upload, retain, or later retrieve it.
The evidence exporter is an offline repository-maintenance command, not a browser or applicant flow. Its versioned path is:
Selected profile + pending/not_run state assertions
|
+--> v1: frozen 58-file compatibility identity
+--> v2: 59 files; registry-aware closure and format-6 bundle pin
|
+--> verify every selected byte against Git HEAD and its profile digest
+--> recheck normalized official-source digests separately from raw bytes
|
v
Canonical manifest: commit/freeze, roles, byte counts, raw hashes, tree hash,
claim boundary, exclusions, known absences, and sources without retained copies
|
v
Single deterministic ZIP_STORED representation outside the repository
|
+--> verify exact member set, paths, metadata, limits, hashes, and bytes
+--> reject prefixes, trailers, compression, encryption, and tampering
|
v
Private sibling staging directory -> canonical loader replay -> exclusive
destination publication only after every check passes
The selected evidence includes public source copies and portable prototype
records; it does not include browser answers, applicant files, accounts,
uploads, identity mappings, credentials, private receipts, portal/submission
material, or unlisted working-tree files. Mutable validation ledgers may be
included only while their profile-pinned bytes and public-state assertions
remain pending, prepared, or not_run.
Restore is inert. It does not change the adopted source snapshot, clear a
source-review hold, promote a verification level, update the originating
repository, or publish guidance. The archive and tree hashes are integrity and
reproducibility records, not signatures, copyright ownership, partner
acceptance, a backup, or a CPRA/sensitive-data export. The exact operational
contract is in EXPORT-RESTORE.md.
The later held-out evaluation contract, the source-change release-receipt templates and tooling, and the beta-operations ADR, runbook, ledger, validator, and tests are outside both the pinned 58-file export profile v1 and the registry-aware 59-file profile v2. Their presence in the repository does not make either fixed package incomplete. A reviewed future profile version must classify and add them before an evidence handoff can claim to include them.
The repository records that AI assisted the checklist-to-requirement mapping and the plain-language action drafts before runtime. Those artifacts are portable files, are bound to workflow and requirement fingerprints, and the generated remedy record carries a recomputed content fingerprint. They remain review-pending. The fingerprint detects copy drift; it does not record review or approval by a named human, planner, counsel, applicant, Woodland staff member, or another jurisdiction. The mapping record includes exact input-source fingerprints and explicitly states that provider, model, and a reproducible run record are unknown or not retained.
No model runs in:
- the deterministic readiness evaluator;
- the readiness CLI;
- the static bundle build;
- the applicant routing matcher; or
- the public browser when the optional AI service is absent or not used.
When the optional AI service directed by ADR 0004 is running and the applicant uses it, a model runs outside the browser, in that service's provider call. That path is described next; it still never runs a model inside the matcher, the evaluator, or the build.
AGENTS.md requires this inventory before an external model call is added.
It describes permit_pathways.ai as implemented; the capability matrix in
docs/PRODUCT-CONTEXT.md carries status and measurements.
Applicant browser (check.html)
|
| only when the applicant opens the AI intake control or presses the
| "explain" control, and only if the service answered a health probe;
| otherwise the page is the static experience above and makes no request
v
Permit Bearings AI service (permit_pathways.ai; 127.0.0.1:8787 by
default, host to be decided)
| request body held in process memory for one request
| applicant content written to disk or logs: none
| applicant record store: none
| rate limiting / abuse controls: deployment-specific, not_run
v
Model provider (Anthropic API, or Amazon Bedrock via the same SDK)
| subprocessor; retention per the provider's terms for the deployment's
| account — to be recorded before any hosted deployment: not_run
v
Service: deterministic checks on the model output
- extracted facts: allowed-value check; supporting quote must occur in
the applicant's text, else the field becomes `unknown`
- explanation: every cited quote must occur in the extracted corpus text
for the named source; unverifiable claims withheld and counted
- staff questions: labeled drafts
v
Browser: drafted facts shown in the editable form for confirmation; labeled
AI-generated explanation with its verified citations; withheld-claim count
Collected fields and purpose:
| Field | Sent to | Purpose | Retained by the service |
|---|---|---|---|
| Free-text project description (EN/ES) | service → provider | draft the structured facts the applicant then confirms | no |
| Confirmed structured facts (the existing 19 names) and jurisdiction slug | service → matcher (local) and → provider | re-run the deterministic matcher; ground the explanation, follow-up answer, and staff questions | no |
| Free-text follow-up question (≤500 characters) | service → provider | answer only from the matched rules' cited passages, or abstain with a staff question | no |
| Interface language | service → provider | choose the output language | no |
| Matched rule IDs computed by the browser | service | parity check against the Python matcher; a mismatch refuses the request | no |
Not collected: name, address, APN, contact details, files, account, or browser identifiers. The free-text field is the one place an applicant could volunteer personal information; the interface tells them not to and the service does not retain it, but a provider receives whatever was typed.
Data flow and subprocessors: browser → service → one model provider. For
the AWS deployment in deploy/ai-service/ (applied 2026-08-21) the facts are: the
service runs as an AWS Lambda function in us-west-2 in the owner's
account; the provider is Amazon Bedrock, model
global.anthropic.claude-sonnet-4-6 through a global inference profile,
which may route the request to another AWS region; Bedrock does not retain
prompts or completions for training and model-invocation logging is off;
CloudWatch keeps request paths and status codes for 14 days and never
bodies; a DynamoDB table keeps one request count per UTC day and nothing
else. No human has signed off on this record; it is what the Terraform
configuration provisions.
Access controls and security boundary: the service binds to localhost by default and allows only configured origins; the provider credential is read from the environment and never written. The prepared hosted deployment adds HTTPS (Function URL), a CORS allowlist of the static site's origin, request size limits (4,000-character description, 500-character question), a per-client limit of 6 model-backed requests per minute, a hard daily cap (default 100, all clients combined) enforced atomically in DynamoDB, and reserved concurrency of 2. It does not authenticate callers, so anyone who reaches the URL can spend the day's budget; that is the accepted trade for a page that keeps no secret. Threat model and abuse review are not done.
Retention and deletion: the service retains nothing, so there is nothing to delete on the application side. Provider-side retention is governed by the provider's terms and must be documented per deployment.
Jurisdiction ownership and export: no applicant record exists to own or export. Prompts, the evaluation set, and the corpus index are repository files.
CPRA and records: a hosted service creates request metadata at the host and the provider. Whether any of it is a public record in a given deployment is a deployment-specific determination; nothing here asserts one.
Deployment-specific review needs: host and subprocessor inventory, privacy review of the free-text field, threat model, cost envelope, operations package, and the approvals ADR 0002 lists — none has been started.
AI-assisted copy cannot create or change a readiness finding. The evaluator does not import the remedy sidecar. The browser recomputes its content fingerprint, rejects invalid review metadata, and withholds action wording when the source state is not current.
The evidence manifest records that one versioned program evaluated one synthetic inventory against one source-bound manifest. It does not establish that:
- the checklist is a complete statement of Woodland requirements;
- a Woodland preapproved plan is currently listed or usable;
- the simulated workflow is applicant-ready or applies to a real project;
- any reported-present file contains the required information;
- the fabricated parcel values describe any real parcel or that parcel or zoning facts are correct;
- documents are internally consistent or legally sufficient;
- an application is complete;
- staff may not request other material;
- the project is eligible or compliant;
- a permit will be approved; or
- applicants, planners, counsel, or a jurisdiction have validated the workflow.
Any future use of real applicant facts, document files, accounts, telemetry, parcel services, or permitting-system data would create a different data flow and require deployment-specific documentation and review. The optional AI service path above is the one such flow this repository has designed; its hosted deployment is still subject to that review.