core

A variant of Infrastructure Asset Registry.

View the interactive variant page →

Infrastructure Asset Registry

Part of the worlds-biggest-software-project initiative.

An open-source, AI-native platform for managing the full lifecycle of physical infrastructure assets -- from inventory and condition assessment to capital planning and compliance reporting -- without vendor lock-in to proprietary GIS platforms.

Infrastructure Asset Registry provides municipalities, transportation departments, and utilities with a structured, GIS-linked inventory of roads, bridges, pipes, culverts, signals, and other long-lived assets. It replaces reactive, complaint-driven maintenance with condition-based priority planning backed by data. The system records location, condition, maintenance history, and financial data for every asset, connecting inspection workflows to capital improvement programmes so agencies can make defensible investment decisions.


Why Infrastructure Asset Registry?

  • Proprietary GIS lock-in is the norm. Nearly every incumbent (Trimble Unity, OpenGov/Cartegraph, AssetWorks) requires Esri ArcGIS licences, significantly increasing total cost of ownership. No open-source alternative with comparable condition management depth exists today.
  • Enterprise platforms price out small agencies. IBM Maximo and Infor EAM require specialist consultants and six-figure implementation budgets, putting modern asset management out of reach for smaller municipalities and school districts.
  • Incumbent mobile apps are unreliable. OpenGov/Cartegraph's mobile app is reported as battery-draining and crash-prone; frequent UI changes create retraining burdens for field crews who need simple, stable tools.
  • Compliance reporting is manual and fragmented. GASB 34 and grant-application reporting requires assembling data across multiple systems. No incumbent offers automated, data-driven compliance report generation out of the box.
  • AI capabilities are siloed or absent. Only iFactory and IBM Maximo offer meaningful AI, but iFactory is a prediction overlay (not a full registry) and Maximo's AI is locked inside IBM's ecosystem. Transparent, explainable AI for condition assessment remains an open gap.

Key Features

Asset Inventory and Hierarchy

  • Unique identification and classification for every asset with full attributes: type, location, dimensions, material, installation date, replacement cost, responsible department
  • Hierarchical organisation from network to segment to component
  • Support for both horizontal (roads, pipes, sewers) and vertical (buildings, facilities) asset types
  • Import wizard with AI-assisted field mapping for migrating legacy spreadsheet, GIS, and paper records

GIS Integration (Vendor-Neutral)

  • Spatial data linking via open standards: GeoJSON, OGC API Features, PostGIS
  • Map-based search, proximity analysis, and network-level views without Esri licence dependency
  • Compatible with QGIS, OpenStreetMap, Leaflet, and OpenLayers
  • Near real-time data synchronisation with external GIS sources

Condition Inspection and Rating

  • Mobile-friendly inspection recording with photo capture and offline support for remote field locations
  • Standardised scoring frameworks: Pavement Condition Index (PCI/ASTM D6433), Bridge Health Index (NBI), CCTV pipe grading, Asset Condition Index (ACI)
  • AI-assisted condition scoring from inspection photos using computer vision
  • Multi-standard condition index support in a unified scoring model

Capital Planning and Scenario Modelling

  • Replacement cost forecasting by asset class and condition band
  • Scenario modelling showing long-term funding impact of different investment levels, including cost of deferral
  • AI-recommended CIP investment allocations based on deterioration models
  • Predictive deterioration modelling with maintenance deferral cost analysis

Work Order Management and Maintenance

  • Work order creation, assignment, tracking, and completion
  • Preventive maintenance scheduling with automated work order generation
  • Natural language work order creation from field voice or text notes
  • Job costing and cost tracking per asset

Reporting and Compliance

  • GASB 34 and ISO 55001-aligned reporting templates
  • Automated grant-application report generation
  • AI-synthesised plain-language reports for elected officials and non-technical stakeholders
  • Natural language query interface for asset data retrieval and ad-hoc reporting

Community and Stakeholder Access

  • Citizen/constituent issue submission portal linked to asset records
  • Community-facing transparency dashboards showing asset conditions and planned capital works
  • Role-based access control for field crews, supervisors, administrators, and finance staff

AI-Native Advantage

Unlike incumbents that bolt AI onto legacy platforms or offer it only as a proprietary overlay, Infrastructure Asset Registry integrates AI as a core capability. Computer vision automates condition scoring from inspection photos, replacing subjective manual ratings. Predictive deterioration models forecast asset failure likelihood based on condition trends, age, material, and environmental factors, giving agencies 30-60 days of advance warning. Natural language interfaces let non-technical staff query asset data and generate reports without BI skills. Automated data migration uses AI to map and transform legacy spreadsheet formats into structured registry schemas, dramatically reducing implementation time.


Tech Stack & Deployment

  • GIS foundation: PostGIS, GeoJSON, OGC API Features -- no proprietary GIS licence required
  • Frontend mapping: Leaflet or OpenLayers for browser-based map views; QGIS integration for advanced spatial analysis
  • Mobile: Offline-capable mobile inspection app for field crews in low-connectivity environments
  • Deployment: Self-hosted, cloud, or hybrid
  • Integration: REST API for connectivity to financial systems, ERP (SAP, Oracle, Munis, Tyler), and SCADA
  • Standards: PCI (ASTM D6433), NBI bridge inspection methodology, ISO 55001 asset management framework, GASB 34 financial reporting

Market Context

The global infrastructure asset management software market serves municipalities, transportation departments, and utilities managing assets worth billions in replacement value. Incumbent pricing follows annual SaaS subscriptions tiered by asset count or municipality population, with enterprise platforms like IBM Maximo and Infor EAM requiring substantial implementation services on top of licence fees. Primary buyers are public works directors, asset management coordinators, and municipal CIOs under increasing regulatory pressure from GASB 34 requirements and federal/state infrastructure funding programmes that mandate demonstrated asset management capability.


Running It

docker compose up -d                     # PostGIS 16-3.4 :54439, Redis :63439, MinIO :59439
cd target && uv sync
uv run alembic upgrade head              # the same command the platform release: step runs
uv run python scripts/seed_frameworks.py --destination dev   # PCI, NBI as data
uv run python scripts/seed.py --destination dev              # a populated demo agency
uv run honcho start                      # API on :8080, Celery worker, beat
curl -s localhost:8080/healthz           # {"status":"ok","db":true,"redis":true,"storage":true}

Full walkthrough: user-docs/getting-started.md · Demo data, per destination: user-docs/demo-data.md · Tests: user-docs/testing.md · Commands: user-docs/useful-commands.md · API: user-docs/api-reference.md and the generated OpenAPI 3.1 document.


Configuration

Every option the application reads is listed below. There is exactly one place that reads configuration — Settings in target/src/iar/config.py — and no service anywhere in the codebase touches os.environ, which a contract test enforces by scanning the source tree.

There is no DATABASE_URL and no REDIS_URL. The platform injects discrete DATABASE_HOST/_PORT/_NAME/_USER/_PASSWORD/_SSL and REDIS_HOST/_PORT/_NAMESPACE/_TLS variables and the application composes its connection strings from them. A settings object with a database_url field works on a laptop and silently fails to connect on every deployed destination.

Destinations never layer. .env.<destination> is the only file consulted for that destination — there is no base file underneath it. Every key a destination needs appears in its own template, which is why the three templates repeat each other rather than sharing a common part:

DestinationTemplateNotes
dev.env.dev.examplerun from the IDE against the compose stack
prod-parity.env.prod-parity.examplelocal full-parity compose deployment
aws.env.aws.exampleplaceholders only; secrets come from the platform

On aws the whole DATABASE_* and REDIS_* namespace, the S3 bucket and credentials, and AUTH_CLIENT_SECRET are deliberately absent from the template. The platform injects them, and a key in the file that the platform also injects shadows the injected value — which points the application at the wrong database with no error at all. Their defaults, shown below, apply there.

Runtime

OptionDefaultWhat it does
APP_NAME439-infrastructure-asset-registry-coreService name in every log line.
APP_ENVlocalFree-text environment label; appears in logs.
APP_URLhttp://localhost:8080The externally reachable base URL, used to build absolute links.
LOG_LEVELINFORoot log level. Logs are one-line JSON on stdout, mapped to the OTel Logs Data Model.
PORT8080The platform contract. A framework default of 3000 or 8000 works locally and is unreachable when deployed.
IAR_WEB_DIST(unset)Directory holding the built SPA. Unset means web/dist relative to the working directory, which is what the container image provides.

Database

DATABASE_SSL=true is honoured with a real TLS context — RDS injects it as true. Credentials are percent-encoded when the DSN is composed, because an unescaped @ in a platform-generated password would otherwise point the application at a different host entirely.

OptionDefaultWhat it does
DATABASE_HOSTlocalhostInjected by the platform.
DATABASE_PORT5432Injected by the platform.
DATABASE_NAMEiarInjected by the platform.
DATABASE_USERiarInjected by the platform.
DATABASE_PASSWORD(empty)Injected by the platform. Never committed.
DATABASE_SSLfalsetrue opens the connection with a verified TLS context.
DATABASE_POOL_SIZE10Connections kept open per process.
DATABASE_MAX_OVERFLOW10Additional connections allowed under burst.
DATABASE_ECHOfalseLogs every SQL statement. Keep it false outside a debugging session: it is the fastest way to get row values into the log.

Redis

Redis is a broker and a cache only, declared durable: false. Every job's source of truth is the Postgres jobs table and every task is idempotent, so a queue entry lost to a failover is re-derivable.

OptionDefaultWhat it does
REDIS_HOSTlocalhostInjected by the platform.
REDIS_PORT6379Injected by the platform.
REDIS_DB0Logical database index. Managed Redis often exposes only 0; REDIS_NAMESPACE is what actually keeps applications apart.
REDIS_NAMESPACEiarMandatory key prefix applied to every key the application writes — cache entries, rate-limit buckets, and the Celery broker's global_keyprefix. Cache-mode Redis may be shared.
REDIS_TLSfalsetrue selects the rediss:// scheme.

Object storage

Inspection media and rendered reports. Only object keys are stored in Postgres. Locally this is the MinIO service in docker-compose.yaml; on aws it is the bucket declared by s3.enabled, with versioning requested and re-checked at runtime by MediaStore.ensure_versioning().

OptionDefaultWhat it does
S3_BUCKETiar-mediaBucket name. Injected on aws.
S3_REGIONus-east-1Bucket region.
S3_ENDPOINT_URL(unset)Point at MinIO locally; leave empty on aws so boto3 uses the real endpoint.
S3_PUBLIC_ENDPOINT_URL(unset)The endpoint a browser must use to follow a presigned download URL, when it differs from the one the application talks to. Set on the local compose stack (http://localhost:59439), where the app reaches MinIO as minio:9000 and no browser can resolve that name; empty everywhere else. The host is part of the SigV4 signature, so the URL is signed for this endpoint rather than rewritten afterwards.
S3_ACCESS_KEY_ID(unset)Injected on aws (IRSA).
S3_SECRET_ACCESS_KEY(unset)Injected on aws (IRSA).
S3_FORCE_PATH_STYLEfalsetrue for MinIO, which does not do virtual-host-style addressing.
MEDIA_MAX_BYTES26214400 (25 MB)Largest accepted inspection photo.

Authentication

Sign-in goes through the platform HAP (OAuth 2.0 + OIDC, PKCE S256). The application never presents an isolated app-only login to a user who already holds a platform session, and users are keyed on sub, never on email.

AUTH_ISSUER on aws is an unresolved placeholder. The platform documentation gives wbsp-auth.wbsp-demo.com and the HAP documentation gives auth.wbsp-demo.com for what is described as the same service (TODO(HAP_ISSUER_HOSTNAME), constitution §Unresolved Platform Constraints). Confirm with the operator before the first aws deploy. Do not guess: a plausible wrong issuer deploys cleanly and fails every sign-in.

OptionDefaultWhat it does
AUTH_ISSUER(empty)OIDC issuer URL. Empty disables authentication wiring entirely.
AUTH_CLIENT_ID(empty)OIDC client id.
AUTH_CLIENT_SECRET(empty)OIDC client secret. Declared under secrets: in wbsp.yaml; a declared secret with no value fails the deploy, which is the intended fail-closed behaviour.
AUTH_REDIRECT_URI(empty)Must match the registered redirect URI exactly.
AUTH_POST_LOGOUT_REDIRECT_URI(empty)Where the HAP returns the browser after sign-out.
AUTH_SCOPESopenid profile emailScope list, comma- or space-separated. The committed templates use commas: uv run --env-file abandons parsing an entire file at the first unquoted space and loads nothing but a warning, at which point every key silently takes its default — including SESSION_COOKIE_SECURE.
SESSION_SECRETchange-meSigning key for the session cookie. Replace on every deployed destination.
SESSION_COOKIE_NAMEiar_sessionConfigurable so two deployments on sibling hostnames cannot overwrite each other's cookie.
SESSION_COOKIE_SECUREtrueLocal destinations set this false deliberately: browsers drop a Secure cookie over http://localhost, and the symptom is a sign-in loop with no error.
SESSION_MAX_AGE_SECONDS28800 (8 h)Session lifetime — a working day, after which the HAP is asked again.
AUTH_DEV_LOGINfalseLocal unattended runs only. Signs in as one named existing account without an OIDC round trip, so the Impeccable pass, the E2E suite and the screenshot capture can reach authenticated views with nobody at the keyboard. Enabling it on a non-local APP_ENV is a startup failure, not a warning. See user-docs/login-bypass.md.
AUTH_DEV_LOGIN_SUB(empty)Which existing account AUTH_DEV_LOGIN signs in as, by sub. No default: a bypass that picks an account for you is one nobody can audit. It grants no authority — roles are read from the database per request, exactly as for a real session.
AUTH_HAP_ISSUER(empty)Injected by the platform, never set by hand. The shared demo HAP issuer, supplied to every demo/sandbox pod at launch. Do not put it in a .env file and do not declare it under secrets: — a demo deploy is fail-closed on declared secrets, so declaring credentials the platform supplies blocks the lane on values nobody can look up.
AUTH_HAP_ID(empty)Injected alongside AUTH_HAP_ISSUER. The shared demo client id, whose redirect is a wildcard across *.wbsp-demo.com — which is what makes sign-in work on a sandbox URL without registering one per host.
AUTH_HAP_SECRET(empty)Injected alongside AUTH_HAP_ISSUER. When all three are present they replace AUTH_ISSUER / AUTH_CLIENT_ID / AUTH_CLIENT_SECRET at startup; when any is missing the baked-in client is kept, so a half-injected client cannot break a working configuration.

Email — optional

OptionDefaultWhat it does
SMTP_HOST(unset)Unset means notifications are in-app only and the API reports email_status: skipped_no_config (FR-079). Nothing else degrades.
SMTP_PORT(unset)
SMTP_USER(unset)
SMTP_PASSWORD(unset)
SMTP_FROM(unset)Required alongside SMTP_HOST for email to be considered configured.
SMTP_TLStrueSTARTTLS.

Assisted capabilities — optional

With no model access configured, GET /api/v1/capabilities reports every capability false, each AI endpoint returns 503 capability_unavailable, and everything else in the product works normally (FR-051). That is a tested contract, not a degraded mode.

OptionDefaultWhat it does
AI_MODEL_CHAT(unset)Enables natural-language query and report synthesis.
AI_MODEL_VISION(unset)Enables computer-vision condition assessment.
AI_API_KEY(unset)Provider credential.
AI_API_BASE(unset)Override for a self-hosted or proxied endpoint. Access routes through a provider-neutral abstraction; no single AI vendor is ever required to run the system.
AI_VISION_CONFIDENCE_THRESHOLD0.75Below this an assessment is flagged requires_human_review. Vision scores are advisory and always overridable, with the override recorded.

Limits and pagination

OptionDefaultWhat it does
RATE_LIMIT_AUTHENTICATED_PER_MINUTE300Per user (FR-066). Exceeded → 429 with Retry-After.
RATE_LIMIT_PUBLIC_PER_MINUTE20Per IP on the citizen surface (FR-039).
PAGINATION_DEFAULT_LIMIT50Page size when the caller names none.
PAGINATION_MAX_LIMIT500Hard cap on limit.

Continuity

OptionDefaultWhat it does
BACKUP_BASISmanagedWhich facility recovery rests on. managed uses the platform's own backups as the RPO basis, with this application owning automated restore verification. self_managed_dump activates the application-owned pg_dump-to-S3 contingency, so a withdrawn PostGIS grant is a configuration change rather than a rewrite. See user-docs/backup-restore.md.

Project Status

This project is in the research and specification phase.
Contributions, feedback, and domain expertise are welcome.


Contributing

We welcome contributions from developers, domain experts, and potential users. See CONTRIBUTING.md for guidelines.

Important: All contributions must be your own original work or clearly attributed open-source material with a compatible licence. Copyright infringement and licence violations will not be tolerated and will result in immediate removal of the offending contribution. If you are unsure whether a piece of code, text, or other material is safe to contribute, open an issue and ask before submitting.


Licence

Licence to be determined. See discussion for context.