Go service running as an ECS Fargate task. Long-polls a single SQS queue for DisasterNotification messages, queries Postgres (homeowners_declared for disaster-specific runs, bq_households for state-wide runs) in 50,000-row batches, pipes the rows as line-delimited GeoJSON straight into the Mapbox Tilesets API via io.Pipe, then creates and publishes a tileset named helpishere.<env>.<disaster_id>. Designed to avoid OOM by streaming.
Role in the system: Transforms household records into Mapbox vector tilesets that the af-frontend renders as the disaster-relief map
Surfaces:
- SQS consumer (af-backend-mapping-service-notifications)
- Mapbox Tilesets API client
- Manual operator-triggered SQS messages
User workflows
Automatic disaster regen
Tileset helpishere.<env>.<disaster_id> available; frontend MapboxGL layer renders affected households
Manual operator regen
Tileset re-generated
State-based regen (experimental)
Tileset for entire state — flagged 'use with caution' (not fully validated)
API endpoints
- SQS
DisasterNotificationTrigger tileset regeneration - OUT-HTTP
POST https://api.mapbox.com/tilesets/v1/sources/{user}/{sourceID}Upload GeoJSON source - OUT-HTTP
POST https://api.mapbox.com/tilesets/v1/{tilesetID}Create tileset from source - OUT-HTTP
POST https://api.mapbox.com/tilesets/v1/{tilesetID}/publishPublish tileset
Third-party APIs
Mapbox Tilesets API v1
Source upload + tileset create/publish
Service dependencies
AWS SQS
Inbound trigger queue (af-backend-mapping-service-notifications)
AWS RDS Postgres (households)
Source of households (homeowners_declared, bq_households)
AWS SSM Parameter Store
Secrets retrieval (DB creds, Mapbox API key)
AWS IAM
Task execution + task roles
af-backend-go-api (upstream)
[planned] Publishes SNS events that fan out to this queue
af-frontend (downstream)
Consumes the published tilesets via mapbox-gl
Analysis
af-map — Prop-Build Analysis
Document Type: Critical Review & Analysis (companion to prop-build-template.md)
Scope: Per-Repo / Per-Module
Subject: af-map (AidFinder Mapping Service)
Reviewer(s): Claude (automated code review)
Date: 2026-04-09
Version: 0.1
Confidence Level: Medium
What would raise confidence: access to CloudWatch metrics and SQS DLQ config in af-infra, a run against real Mapbox, and an interview with Marek Burda on the state-wide path.
Inputs Reviewed:
- Prop-build doc:
data/af-map.yaml - Source tree:
/Users/andres/src/af/af-map/(Go 1.26, ~4.7k LoC) - Companion files:
data/af-map/{api-examples,data-flow,deployment,runbook}.md
Part A — Per-Repo / Per-Module Analysis
A.1 Executive Summary
- Overall health: A small, focused, well-layered Go worker that does one thing (Postgres -> Mapbox tileset) reasonably well, with a clever streaming design but meaningful gaps in error handling, PII governance, and operational visibility.
- Top risk: Full household PII (names, addresses, demographics) is streamed to Mapbox and stored in vector tilesets with no application-level access controls or audit trail — see A.4.1 and A.11.
- Top win / thing worth preserving:
io.Pipe-based streaming uploader inservice/infrastructure/mapbox/tileset.go:26-69wired throughmapgeneration.go:77-92— a genuinely memory-efficient design worth propagating. - Single recommended next action: Add an explicit DLQ + Mapbox source cleanup-on-failure path, and justify-or-remove every
//nolint:gosec(4 instances). - Blocking unknowns: SQS DLQ / visibility-timeout settings live in af-infra and were not reviewed; no measured throughput or CloudWatch metrics available; FEMA Privacy Act applicability of source data is unknown.
A.2 Health Scorecard
| # | Dimension | Score (1–5) | Justification |
|---|---|---|---|
| 1 | Module overview / clarity of intent | 4 | README + hexagonal layout (cmd/, service/application, service/infrastructure, domain/) make intent obvious. |
| 2 | External dependencies | 4 | Small, mainstream Go deps (aws-sdk-go-v2, pgx/v5, scany, validator, tint). |
| 3 | API endpoints | 3 | No HTTP surface; the SQS DisasterNotification contract is validated (service/infrastructure/sqs/sqs.go:131) but undocumented outside YAML. |
| 4 | Database schema | 3 | Schema owned upstream; repo only queries. Two tables (homeowners_declared, bq_households) with reasonable pagination. |
| 5 | Backend services | 4 | Single-purpose worker, cleanly factored into application + infrastructure layers. |
| 6 | WebSocket / real-time | 3 | SQS long-poll, sequential (MaxNumberOfMessages=1), no SNS publishing; simple but serialized. |
| 7 | Frontend components | N/A | Backend-only. |
| 8 | Data flow clarity | 4 | mapgeneration.go:50-100 -> mapbox.go:43-70 -> tileset.go is linear and readable. |
| 9 | Error handling & resilience | 2 | No DLQ in-app, no circuit breaker, no cleanup of stale Mapbox sources on failure (tileset.go:61-66), errors only logged then the message is left for SQS retry (sqs.go:91-105). |
| 10 | Configuration | 4 | Env-var driven via SSM; env-gated tileset naming is explicit in mapbox.go:46-52. |
| 11 | Data refresh patterns | 3 | Event-driven only; no incremental update (is_updated parsed but unused). |
| 12 | Performance | 3 | Streaming avoids OOM, but serial 1-msg-at-a-time polling and 120-minute HTTP timeout (mapbox.go:16) make tail latency unbounded. |
| 13 | Module interactions | 4 | Clear: SQS in, Postgres in, Mapbox out; boundaries are respected. |
| 14 | Troubleshooting / runbooks | 3 | data/af-map/runbook.md exists; in-repo README documents manual Mapbox cleanup curls. |
| 15 | Testing & QA | 3 | sqs_test.go is 428 LoC with testify; no coverage number, no Mapbox integration test, no load test. |
| 16 | Deployment & DevOps | 4 | GitHub Actions -> ECR -> ECS CodeDeploy blue/green; manual deploy dispatch documented. |
| 17 | Security & compliance | 2 | PII streamed to a third-party tileset store with no app-level audit log; 4 //nolint:gosec without justification. |
| 18 | Documentation & maintenance | 4 | README is clear, YAML prop-build is thorough, changelog tracked. |
| 19 | Roadmap clarity | 3 | section_19_roadmap lists planned items and acknowledged debt, but no dates/owners. |
Overall score: 3.28 (average of 18 rated dimensions; dim 7 N/A). Weighted reading: structural dimensions (1, 5, 8, 13, 16, 18) are solidly 4; operational and security dimensions (9, 17) drag the honest average into the low 3s and are where remediation should focus.
A.3 What's Working Well
-
Strength: Streaming
io.Pipeuploader — Postgres pagination batches are piped straight into the Mapbox multipart body, so memory is bounded regardless of disaster size.- Location:
service/infrastructure/mapbox/tileset.go:26-69+service/application/map-generation/mapgeneration.go:77-92 - Why it works: avoids the obvious OOM footgun on large disasters; producer/consumer are decoupled by the pipe and errors propagate via
pw.CloseWithError. - Propagate to: any other worker in the platform that materializes large Postgres result sets to external APIs (af-targeting is the obvious candidate).
- Location:
-
Strength: Clean hexagonal layering —
cmd/mapwires concrete infrastructure into application services that depend only on small interfaces (MapGenerationService,HouseholdService).- Location:
service/application/map-generation/mapgeneration.go:17-26 - Why it works: substitutable seams for testing; infrastructure is swappable without rewriting the application.
- Propagate to: af-backend-go-api workers that currently couple handlers to concrete clients.
- Location:
-
Strength: Explicit
count == 0short-circuit before uploading.- Location:
service/application/map-generation/mapgeneration.go:54-75 - Why it works: avoids creating empty Mapbox sources/tilesets and the operational mess of cleaning them up.
- Location:
A.4 What to Improve
A.4.1 P0 — PII exposure on Mapbox with no app-level audit or cleanup
- Problem: Full household PII (adult names, street addresses, lat/lon, demographics) is streamed to Mapbox vector tilesets and stored indefinitely. The published tileset properties include
household_name,bq_household_id, and lat/lon. There is no application-level audit log of what was published when, and no automated cleanup of stale sources on failure. - Evidence:
service/infrastructure/mapbox/household.go:33-54writeshouseholdName(derived fromBQAdultsFullNames) and coordinates into every GeoJSON feature;service/infrastructure/mapbox/tileset.go:61-66returns error on non-200 but does NOT delete the partially-uploaded source; README manual cleanup curls confirm this is operator-driven.section_17_security_compliance.data_protection.pii_handlingindata/af-map.yamlflags this as HIGH RISK. - Suggested change: (a) emit a structured audit record on every
UploadDeclaredHouseholdsToMapboxstart/success/failure, including sourceID and row count; (b) add a deferred cleanup step that deletes the Mapbox source if publish fails; (c) confirm Mapbox ToS permits PII storage and minimize properties. - Estimated effort: M
- Risk if ignored: regulatory exposure (FEMA Privacy Act if applicable), breach of Mapbox ToS, and inability to answer "what data was shared, when" during an incident.
A.4.2 P1 — No DLQ handling or poison-message protection in-app
- Problem: Message processing errors are logged and the message is left in the queue for SQS-default retry. There is no max-retry guard, no DLQ handoff in code, and no metric on failure count per message.
- Evidence:
service/infrastructure/sqs/sqs.go:91-105continues on both parse and handler errors without deleting;section_9_error_handling.circuit_breakers.applicable: falsein YAML. - Suggested change: Read
ApproximateReceiveCount; after N failures, move to an explicit DLQ or delete with a loud error metric. Emit a CloudWatch metric for failed handles. - Estimated effort: S
- Risk if ignored: a single poison
DisasterNotificationloops forever, consuming the single-threaded worker and blocking all other disasters.
A.4.3 P1 — Serialized single-message worker is a throughput bottleneck
- Problem:
maxMessages = 1(sqs.go:19) and a synchronous handler mean one disaster blocks the entire service. Mapbox upload can take up to 120 minutes (mapbox.go:16), so one bad disaster starves the queue. - Evidence:
service/infrastructure/sqs/sqs.go:19,service/infrastructure/mapbox/mapbox.go:16. - Suggested change: Run N worker goroutines with bounded concurrency, or document and alert on SQS
ApproximateAgeOfOldestMessage. Reduce the 120m timeout and rely on SQS visibility-timeout extension for long uploads. - Estimated effort: M
- Risk if ignored: backed-up queue during multi-disaster events; no way to hit a reasonable tile-publish SLO.
A.4.4 P2 — Unjustified //nolint:gosec directives
- Problem: Four
//nolint:gosecwith no rationale (README §171 lists fixing them as tech debt). - Evidence:
service/application/map-generation/mapgeneration.go:51,domain/household/postgres/household.go:48,58,80. - Suggested change: Add a one-line justification to each (likely int -> uint32 conversion for disaster_id) or refactor to eliminate the cast.
- Estimated effort: S
- Risk if ignored: security-review noise; real gosec findings will be drowned out.
A.4.5 P2 — is_updated flag parsed but unimplemented
- Problem: The
DisasterNotificationschema carriesis_updated, and the README acknowledges incremental updates are not supported; every run is a full rebuild. - Evidence:
service/infrastructure/sqs/model/model.go:7-12+section_19_roadmap.tech_debt[0]in YAML. - Suggested change: Either delete the field until it's implemented, or implement the update path against Mapbox's tileset-source PATCH.
- Estimated effort: M
- Risk if ignored: contract rot; upstream callers will assume the flag does something.
A.5 Things That Don't Make Sense
-
Observation: The "state-based regen" path is gated on
DisasterID == 0rather than on the presence ofStateName, which makes the branch implicit.- Location:
service/application/map-generation/mapgeneration.go:50-92 - Hypotheses considered: convenience; validator already enforces exactly-one-of at the boundary.
- Question for author: can this become an explicit tagged union in the notification model?
- Location:
-
Observation: The tileset ID in dev omits the environment prefix (
helpishere.<disaster_id>) while stg/prod include it.- Location:
service/infrastructure/mapbox/mapbox.go:46-52 - Hypotheses considered: avoid breaking existing dev tileset; historical compatibility.
- Question for author: why not always prefix (
helpishere.dev.<id>) for uniformity?
- Location:
A.6 Anti-Patterns Detected
A.6.1 Code-level
- God object / god function
- Shotgun surgery
- Feature envy
- Primitive obsession
- Dead code —
is_updatedfield parsed and validated but never branched on. - Copy-paste / duplication
- Magic numbers / unexplained constants —
maxMessages = 1(sqs.go:19),mapboxUploadMaxWaitingTime = 120m(mapbox.go:16). - Deep nesting (>3 levels)
- Long parameter lists
- Boolean-flag parameters
A.6.2 Architectural
- Big ball of mud
- Distributed monolith
- Chatty services
- Leaky abstraction
- Golden hammer
- Vendor lock-in without exit strategy — Mapbox Tilesets API is baked in; no abstraction for a different tile backend.
- Stovepipe
- Missing seams for testing
A.6.3 Data
- God table
- EAV abuse
- Missing indexes on hot queries (not verified — schema upstream)
- N+1 queries
- Unbounded growth / no retention policy — Mapbox tilesets and sources are only deleted manually.
- Nullable-everything schemas
- Implicit coupling via shared database
A.6.4 Async / Ops
- Poison messages with no dead-letter queue — no in-app DLQ logic.
- Retry storms / no backoff
- Missing idempotency keys on non-idempotent ops — re-processing the same
disaster_idgrows the tileset (documented footgun). - Hidden coupling via shared state
- Work queues without visibility / depth metrics — no CloudWatch custom metrics.
A.6.5 Security
- Secrets in code,
.envcommitted, or logs - Missing authn/z on internal endpoints
- Overbroad IAM roles
- Unvalidated input crossing a trust boundary (validator is present)
- PII/PHI in logs or error messages — PII storage in downstream Mapbox tileset (
household.go:33-54); no boundary log/audit. - Missing CSRF / XSS / SQLi / SSRF protections (no web surface)
A.6.6 Detected Instances
| # | Anti-pattern | Location (file:line) | Severity (P0/P1/P2) | Recommendation |
|---|---|---|---|---|
| 1 | Dead code (is_updated unused) | service/infrastructure/sqs/model/model.go:7-12; service/application/map-generation/mapgeneration.go:50-100 | P2 | Implement or drop from schema. |
| 2 | Magic numbers | service/infrastructure/sqs/sqs.go:19; service/infrastructure/mapbox/mapbox.go:16 | P2 | Move to config with doc-comments. |
| 3 | Vendor lock-in | service/infrastructure/mapbox/*.go | P2 | Extract a TileBackend interface at the application boundary. |
| 4 | Unbounded growth | service/infrastructure/mapbox/mapbox.go:43-70; README cleanup curls | P1 | Cleanup-on-failure + periodic reaper. |
| 5 | Poison messages / no DLQ | service/infrastructure/sqs/sqs.go:89-106 | P1 | Honor ApproximateReceiveCount; wire explicit DLQ. |
| 6 | Missing idempotency keys | service/application/map-generation/mapgeneration.go:50-100 | P1 | Delete-or-replace source/tileset before upload. |
| 7 | Missing work-queue metrics | service/infrastructure/sqs/sqs.go | P2 | Emit CloudWatch metrics. |
| 8 | PII governance gap | service/infrastructure/mapbox/household.go:33-54 | P0 | Audit log on publish; minimize tileset properties. |
A.7 Open Questions
-
Q: Is the target SQS queue actually configured with a DLQ in af-infra, and with what
maxReceiveCount?- Blocks: A.4.2, A.6.4 row 1.
- Who can answer: af-infra owner.
-
Q: Does Mapbox ToS permit storing full PII in a published tileset? Is there a signed data-processing addendum?
- Blocks: A.4.1, A.11.
- Who can answer: legal / data-privacy owner.
-
Q: Are
homeowners_declaredrows derived from FEMA IA data?- Blocks: FEMA Privacy Act assessment.
- Who can answer: af-backend-go-api data owner.
A.8 Difficulties Encountered
-
Difficulty: No access to CloudWatch metrics, SQS configuration, or deployed task definitions at review time.
- Impact on analysis: cannot verify whether a DLQ exists, cannot measure observed throughput or error rate, cannot confirm
DATABASE_SSL_MODE=requirein prod. All performance and resilience findings are structural, not empirical. - Fix that would help next reviewer: commit a read-only link to the CloudWatch dashboard and paste representative
aws sqs get-queue-attributesoutput intodata/af-map/runbook.md.
- Impact on analysis: cannot verify whether a DLQ exists, cannot measure observed throughput or error rate, cannot confirm
-
Difficulty: The state-wide path is marked "experimental" but has no test coverage asserting it.
- Impact on analysis: cannot say whether
bq_householdspagination terminates cleanly for large states. - Fix that would help next reviewer: an integration test against LocalStack exercising the
DisasterID == 0branch.
- Impact on analysis: cannot say whether
-
Difficulty: Only skimmed the 428-line
sqs_test.go; did not enumerate every case.- Impact on analysis: test-quality claims are directional, not definitive.
A.9 Risks & Unknowns
A.9.1 Known risks
| # | Risk | Likelihood (L/M/H) | Impact (L/M/H) | Mitigation |
|---|---|---|---|---|
| 1 | Poison DisasterNotification blocks single-worker queue | M | H | Add DLQ handoff (A.4.2). |
| 2 | Orphan Mapbox source after mid-upload failure | M | M | Cleanup-on-failure in mapbox.go (A.4.1). |
| 3 | PII disclosed via published tileset URL | L | H | Audit, minimize properties (A.4.1). |
| 4 | Re-run on duplicate disaster_id grows tileset unbounded | M | M | Delete-before-upload idempotency. |
| 5 | Credentials mis-scoped in SSM | L | H | External review of IAM policies in af-infra. |
A.9.2 Unknown unknowns
- Area not reviewed: actual SQS queue + DLQ configuration.
- Reason: lives in af-infra; out of scope.
- Best guess at risk level: medium — the repo assumes default retries.
- Area not reviewed: Postgres query plans and index coverage.
- Reason: no DB access; schema owned upstream.
- Best guess at risk level: medium — 50k-row pages over
bq_householdscould be slow on a cold index.
- Area not reviewed: af-frontend Mapbox consumption.
- Reason: out of scope for per-repo analysis.
- Best guess at risk level: low for this repo.
- Area not reviewed: the 428-line
sqs_test.goin detail.- Reason: time.
- Best guess at risk level: low.
A.10 Technical Debt Register
| # | Debt item | Quadrant | Estimated interest | Remediation |
|---|---|---|---|---|
| 1 | No DLQ handling in-app (sqs.go:89-106) | Reckless & Inadvertent | High — one poison message stalls the worker | Honor ApproximateReceiveCount; explicit DLQ move. |
| 2 | is_updated parsed but unused | Prudent & Deliberate | Low now, Medium later | Implement or drop. |
| 3 | 4x //nolint:gosec without justification | Reckless & Inadvertent | Low | Add justification or refactor casts. |
| 4 | Manual Mapbox source/tileset cleanup | Reckless & Deliberate | Medium — operator toil, audit gap | Cleanup-on-failure + orphan reaper. |
| 5 | maxMessages = 1 serial worker | Prudent & Deliberate | Medium in multi-disaster events | Bounded goroutine pool. |
| 6 | 120-minute HTTP timeout | Reckless & Inadvertent | Medium — hides tail latency | Lower + SQS visibility extension. |
| 7 | DATABASE_RO_HOST missing from .env.common | Prudent & Inadvertent | Low | Add with default. |
| 8 | Tileset naming asymmetry dev vs stg/prod | Prudent & Inadvertent | Low | Normalize naming. |
A.11 Security Posture (lightweight STRIDE)
| Category | Threat present? | Mitigated? | Gap |
|---|---|---|---|
| Spoofing (identity) | Low (IAM-only surface) | Yes (IAM task role) | — |
| Tampering (integrity) | Medium — SQS message is the trust boundary | Partially (validator on DisasterNotification) | No signature; anyone with SQS write perms can trigger a regen. |
| Repudiation | High — no audit trail of who/when published which PII tileset | No | Add audit log of publish events. |
| Information Disclosure | High — full household PII in published Mapbox tileset | Partially (env-prefixed tileset obscurity) | No access control on tiles themselves. |
| Denial of Service | Medium — single-worker + 120-min HTTP timeout | No | Bounded concurrency, shorter timeouts, DLQ. |
| Elevation of Privilege | Low | Yes (least-privilege IAM per YAML) | Not independently verified. |
A.12 Operational Readiness
| Capability | Present / Partial / Missing | Notes |
|---|---|---|
| Structured logs | Present | tint + slog with context. |
| Metrics | Missing | No custom CloudWatch metrics emitted from the app. |
| Distributed tracing | Missing | No OTel / X-Ray instrumentation. |
| Actionable alerts | Partial | YAML lists CloudWatch alarms as TBD. |
| Runbooks | Present | data/af-map/runbook.md + README. |
| On-call ownership defined | Partial | CODEOWNERS exists; rotation not in-repo. |
| SLOs / SLIs | Missing | None declared. |
| Backup & restore tested | N/A | Stateless worker. |
| Disaster recovery plan | Missing | Not documented in repo. |
| Chaos / failure testing | Missing | None. |
A.13 Test & Quality Signals
- Coverage (line / branch): not reported in repo (
section_15_testing.unit.coverage_pct: null); CI uploads to Codecov. - Trend: unknown.
- Flake rate: unknown.
- Slowest tests: unknown.
- Untested critical paths: Mapbox 3-step publish (no integration test); state-wide
DisasterID == 0branch. - Missing test types: [ ] unit (partial) [x] integration [x] e2e [x] contract [x] load [x] security/fuzz
A.14 Performance & Cost Smells
- Hot paths: Postgres pagination ->
io.Pipe-> Mapbox multipart upload. - Suspected bottlenecks: serial 1-message SQS polling (
sqs.go:19); Mapbox publish latency; 50k-row page size. - Wasteful queries / loops:
countquery before upload is a small extra round-trip but worth it to skip empty. - Oversized infra / idle resources: 2 vCPU / 8 GB Fargate for a mostly I/O-bound worker — worth measuring.
- Cache hit/miss surprises: N/A — no caches.
A.15 Bus-Factor & Knowledge Risk
- Who is the only person who understands X? Inferring from
meta.authors(Marek Burda, Matúš Bafrnec); not verified. - What breaks if they disappear tomorrow? The state-wide experimental path and Mapbox ToS context.
- What is undocumented tribal knowledge? The manual Mapbox cleanup workflow and the rationale for dev vs stg/prod naming asymmetry.
- Suggested knowledge-transfer actions: capture the Mapbox cleanup flow as a
make clean-orphansscript; record a note explaining (or fix) the naming asymmetry.
A.16 Compliance Gaps
| Regulation | Requirement | Status | Gap | Remediation |
|---|---|---|---|---|
| Mapbox ToS (PII in tilesets) | Permitted data types & retention | Unknown | No documented review | Legal review + written decision record. |
| FEMA Privacy Act (if applicable) | Downstream disclosure in SORN | Unknown | Source-of-data lineage unclear | Confirm household provenance; update upstream Privacy Act Statement if needed. |
| NIST 800-53 AU-2/AU-12 (audit events) | Audit-log publish operations on PII | Missing | No app-level audit trail | Emit structured audit record on every publish. |
A.17 Recommendations Summary
| Priority | Action | Owner (suggested) | Effort | Depends on |
|---|---|---|---|---|
| P0 | Add app-level audit log + cleanup-on-failure for Mapbox publishes; minimize tileset properties (A.4.1, A.6.6 row 8, A.16 row 3) | af-map maintainer + data-privacy | M | Legal input on Mapbox ToS |
| P0 | Legal/privacy review of PII in Mapbox tilesets and document the decision (A.11, A.16 row 1) | data-privacy | S | — |
| P1 | Honor ApproximateReceiveCount and wire explicit DLQ handoff (A.4.2, A.6.6 row 5) | af-map maintainer | S | af-infra DLQ exists |
| P1 | Delete-before-upload idempotency on duplicate disaster_id (A.6.6 row 6) | af-map maintainer | S | — |
| P1 | Bounded-concurrency worker + reduce 120-minute HTTP timeout (A.4.3, A.10 rows 5-6) | af-map maintainer | M | — |
| P1 | Emit CloudWatch metrics: handle duration, success/fail count, households/sec (A.6.6 row 7, A.12) | SRE | S | — |
| P2 | Justify or remove 4x //nolint:gosec (A.4.4, A.10 row 3) | af-map maintainer | S | — |
| P2 | Implement or delete is_updated (A.4.5, A.10 row 2) | af-map maintainer + upstream | M | Upstream contract |
| P2 | Normalize dev vs stg/prod tileset naming (A.5 obs 2, A.10 row 8) | af-map maintainer | S | Migration plan for existing dev tilesets |
| P2 | Add DATABASE_RO_HOST to .env.common (A.10 row 7) | af-map maintainer | S | — |
| P2 | Integration test for state-wide DisasterID == 0 path against LocalStack (A.8, A.13) | af-map maintainer | M | — |
Environment variables
| Name | Purpose |
|---|---|
ENVIRONMENT* | {local|dev|stg|prod} — controls tileset naming |
DATABASE_HOST* | Writer Postgres host |
DATABASE_RO_HOST* | Read-only Postgres host |
DATABASE_PORT* | Postgres port |
DATABASE_USERNAME* | DB user |
DATABASE_PASSWORD* | DB password |
DATABASE_DB_NAME* | DB name |
DATABASE_SSL_MODE* | {allow|disable|require} |
MAPBOX_API_KEY* | Mapbox token (create/publish scopes) |
MAPBOX_USERNAME* | Mapbox account namespace (always 'helpishere') |
SQS_QUEUE_NAME* | Queue to long-poll |
AWS_REGION | AWS region (defaults to us-east-1) |
LOG_LEVEL | slog level |
