Metadata-Version: 2.5
Name: honua-migrate
Version: 0.9.0
Summary: Open-source assessment and migration tooling for Honua.
Project-URL: Homepage, https://github.com/honua-io/honua-migrate
Project-URL: Issues, https://github.com/honua-io/honua-migrate/issues
Project-URL: Repository, https://github.com/honua-io/honua-migrate
Project-URL: Changelog, https://github.com/honua-io/honua-migrate/blob/trunk/CHANGELOG.md
Author: Honua
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: arcgis,esri,filegdb,gis,migration,readiness
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: click<9,>=8.1
Requires-Dist: jsonschema<5,>=4.21
Requires-Dist: requests<3,>=2.31
Requires-Dist: tenacity<10,>=8.2
Requires-Dist: typer<1,>=0.12
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: hatch<2,>=1.9; extra == 'dev'
Requires-Dist: httpx<1,>=0.27; extra == 'dev'
Requires-Dist: mypy<3,>=1.10; extra == 'dev'
Requires-Dist: packaging<27,>=24; extra == 'dev'
Requires-Dist: pip-audit<3,>=2.9; extra == 'dev'
Requires-Dist: pytest<10,>=8; extra == 'dev'
Requires-Dist: responses>=0.25; extra == 'dev'
Requires-Dist: ruff<1,>=0.5; extra == 'dev'
Provides-Extra: filegdb
Requires-Dist: pyogrio<0.14,>=0.12; extra == 'filegdb'
Provides-Extra: smoke
Requires-Dist: pytest<10,>=8; extra == 'smoke'
Requires-Dist: responses>=0.25; extra == 'smoke'
Description-Content-Type: text/markdown

# honua-migrate

[![CI](https://github.com/honua-io/honua-migrate/actions/workflows/ci.yml/badge.svg?branch=trunk)](https://github.com/honua-io/honua-migrate/actions/workflows/ci.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/honua-io/honua-migrate/badge)](https://scorecard.dev/viewer/?uri=github.com/honua-io/honua-migrate)
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)

> **Command transition:** `honua-migrate assess` is now the primary assessment
> surface. The `honua-esri-assess` command, module invocation, Python imports,
> and artifact contracts remain compatible through the documented transition
> window, with removal no earlier than `honua-migrate` 1.2. See the
> [assessment transition policy](docs/assessment-transition.md).

An Apache-2.0 migration command-line suite whose **read-only assessment
surface** inventories an organization's Esri
footprint — ArcGIS Online, ArcGIS Server / Enterprise, and FileGDB workspaces —
and produces a versioned `EsriFootprint.json` artifact plus human-readable
Markdown reports: a readiness report, a per-shop-profile migratability
verdict, and a crosswalk from that footprint to Honua capability keys. It
exists so GIS teams can size a migration to
[Honua](https://honua.io) (or simply audit their own estate) before committing
to anything. The suite is Apache-2.0 by design so your security team can audit
every line before pointing it at production.

## Assessment is read-only and no-phone-home, verifiably

The assessment surface is built for skeptical review. The guarantees below
are enforced in code and by tests in this repository — not just promised:

- **Strictly read-only assessment.** Every request against an Esri system is an HTTP
  `GET`. The HTTP wrappers expose no write helpers; no `POST`/`PUT`/`DELETE`/
  `PATCH` is ever issued.
- **No network telemetry.** No usage pings, crash uploads, or update checks —
  there is not even an opt-in sink. The only hosts ever contacted are the
  `--target` you supply to `scan`, or the crosswalk URL you explicitly pass to
  `caps --crosswalk` (never fetched by default — see
  [Capability crosswalk](#capability-crosswalk-caps) below). Enforced by
  [`tests/test_no_telemetry.py`](tests/test_no_telemetry.py) and
  [`tests/smoke/test_no_network.py`](tests/smoke/test_no_network.py), which
  fail CI if outbound traffic appears.
- **It mints no credentials.** You run it anonymously or hand it a
  pre-existing token via `--token-env VAR` (an environment variable name).
  There is deliberately no `--token` flag, no username/password input, and no
  `generateToken` call.
- **Secrets never leak into outputs.** Tokens, query strings, and URL userinfo
  are redacted from logs and are never written into artifacts or diagnostics.
- **It never opens your databases.** Storage information comes from documented
  ArcGIS REST metadata only — no ArcSDE/DBMS connections, no GDB internals.
- **Everything stays on your machine.** Artifacts are written to local files
  (or stdout). Nothing is uploaded anywhere.

Before running against production, see
[Prerequisites & least-privilege access](docs/operators/prerequisites-and-least-privilege.md)
for the exact endpoints read at each access tier and the minimum privileges to
grant. An anonymous "Tier 1" scan needs no credentials at all.

## Status

Alpha, pre-1.0 (current source version 0.7.x — see the [CHANGELOG](CHANGELOG.md)).
The `EsriFootprint.json` schema is at **v0.2** and unstable until v1.0:
breaking changes are permitted between v0.x minors, per the
[versioning policy](docs/schemas/versioning.md). An installed command's
`--version` output is the authoritative application version.

## Quick start

Requires Python 3.11+.

Install the application in an isolated environment:

```bash
pipx install honua-migrate
honua-migrate assess --help
honua-esri-assess --help  # supported compatibility command
```

For development against an unreleased source checkout:

```bash
git clone https://github.com/honua-io/honua-migrate
cd honua-migrate
python3 -m pip install .
```

Scan an ArcGIS Online org (anonymous scans work too — just omit the token):

```bash
export AGOL_TOKEN="..."   # optional, pre-existing token
honua-migrate assess scan agol \
  --target https://yourorg.maps.arcgis.com/sharing/rest \
  --token-env AGOL_TOKEN \
  --output EsriFootprint.json \
  --validate
```

Then render the human-readable companions:

```bash
honua-migrate assess report  --input EsriFootprint.json --output readiness-report.md
honua-migrate assess verdict --input EsriFootprint.json
honua-migrate assess caps    --input EsriFootprint.json
```

Inspect or validate against the bundled schema at any time:

```bash
honua-migrate assess schema show
honua-migrate assess schema validate EsriFootprint.json
```

## Commands

Run `honua-migrate --help` for the complete migration command tree, or
`honua-migrate assess --help` for assessment options. The compatibility forms
`honua-esri-assess --help` and `python -m honua_esri_assess --help` remain
available. Every assessment `scan` subcommand is read-only against the target.

| Command | What it does |
|---------|--------------|
| `scan agol` | Inventory an ArcGIS Online / Portal org via the Portal Sharing REST API. |
| `scan server` | Walk an ArcGIS Server REST catalog (folders, services, layer detail). |
| `scan filegdb` | Read a local FileGDB inventory descriptor (`_inventory.json`); no network. |
| `scan filegdb-workspace` | Read-only `pyogrio`/GDAL metadata scan of a local `.gdb` directory (requires the `filegdb` extra). |
| `scan rbac` | Export identity/RBAC posture (users, roles, groups, per-service permissions) to the sibling `EsriAccessFootprint.json`. |
| `report` | Render a Markdown readiness report from a footprint. |
| `verdict` | Render a per-shop-profile migratability verdict (go / conditional / no-go, with explicit hard lock-in boundaries such as Utility Network, Parcel Fabric, and LRS). |
| `caps` | Crosswalk a footprint to Honua capability keys: `honua-caps.json` + a Markdown summary + a shareable catalog URL. See [Capability crosswalk](#capability-crosswalk-caps). |
| `schema show` / `schema validate <file>` | Print the bundled JSON Schema / validate an artifact against it. |
| `version` | Print package and bundled schema versions (also `--version`). |

Common `scan` options: `--output` (default `./EsriFootprint.json`; existing
files are not overwritten unless you pass `--force`), `--token-env VAR`,
`--validate`, `--timeout`, `--max-retries`, `--user-agent`, `--log-format
text|json`, `--log-level`. `report`, `verdict`, and `caps` accept `--input -` /
`--output -` for stdin/stdout and `--strict` to fail on schema-invalid input
instead of rendering warnings.

## Capability crosswalk (`caps`)

`caps` maps the same deterministic capability detection the `verdict` engine
uses (`honua_esri_assess.verdict.registry` — portal item types, server
`serviceType`s, and per-service capability tokens already in
`EsriFootprint.json`) onto **Honua capability keys**, via a versioned
crosswalk document:

```bash
honua-migrate assess caps --input EsriFootprint.json
# writes ./honua-caps.json, prints a Markdown summary + the shareable URL
```

```bash
honua-migrate assess caps \
  --input EsriFootprint.json \
  --json honua-caps.json \
  --output caps-summary.md
```

It emits:

1. **`honua-caps.json`** (`--json`, default `./honua-caps.json`): `schemaVersion`,
   `generatedAt`, the source footprint reference, per-capability entries
   (Honua capability key, contributing assess key(s), matched inventory count,
   tier), an `unmapped` list, `diagnostics`, a serving-unit estimate
   (`unitsEstimate`), and the shareable `url`.
2. A **Markdown summary** (`--output`, default stdout), styled like the
   `report`/`verdict` output.
3. The **shareable catalog URL** —
   `https://honua.io/capabilities.html?caps=<keys>&units=<estimate>` — always
   printed to stdout in addition to the JSON. `units` is derived from the
   footprint's server facet (federated server / host count) when available,
   and omitted entirely (never `units=0`) otherwise.

**Nothing in the footprint's detected inventory is dropped.** Every
assess-registry capability the footprint triggers ends up in `honua-caps.json`
one of two ways: mapped into `capabilities`, or listed in `unmapped` with a
`reason` of `"unmapped"` (known capability, no capability-key mapping yet) or
`"not-supported"` (a hard Esri lock-in such as Utility Network, Parcel
Fabric, or LRS — there is no Honua equivalent, by design).

### Draft crosswalk (temporary)

The crosswalk `caps` ships with today
(`src/honua_esri_assess/data/honua-crosswalk.fixture.json`) is a **draft
placeholder**, not the canonical mapping. The canonical
`capability-keys.v1.json` artifact — with the reconciled
`esri-assess-registry → capability` crosswalk — is produced by honua-server
(honua-io/honua-server#2893) and will replace it. Every `caps` run stamps the
crosswalk's own `source` string into `honua-caps.json`
(`"crosswalk.source"`) so output generated against the draft is never
mistaken for the reconciled mapping.

### Air-gapped usage

`caps` makes **no network call by default** — the bundled draft fixture is
read from the installed package. Use `--crosswalk <path>` to point at a local
file (e.g. a copy of the published artifact carried into an air-gapped
network) with zero network access:

```bash
honua-migrate assess caps --input EsriFootprint.json --crosswalk ./capability-keys.v1.json
```

`--crosswalk` also accepts an `http(s)://` URL once the canonical artifact is
published — this is the *one* deliberate, explicit exception to the tool's
no-network posture, and it only runs when you pass a URL yourself:

```bash
honua-migrate assess caps --input EsriFootprint.json \
  --crosswalk https://example.com/capability-keys.v1.json
```

The crosswalk document is validated at load: an `esri-assess-registry` key
that does not exist in `honua_esri_assess.verdict.registry.CAPABILITY_REGISTRY`
fails loudly (`report.crosswalk.invalid`, exit code `5`) rather than silently
mapping nothing.

## Supported sources

| Source | Target (`--target`) | Notes |
|--------|---------------------|-------|
| ArcGIS Online / Portal | Sharing REST base, e.g. `https://yourorg.maps.arcgis.com/sharing/rest` | The scanner appends `portals/self`, `search`, `community/groups`, `content/items/<id>` to this base; a higher-level portal URL yields `partial-coverage` diagnostics instead of an inventory. |
| ArcGIS Server | `https://host`, `https://host/arcgis`, `…/arcgis/rest`, or `…/arcgis/rest/services` — canonicalized internally | Deep layer probes run for `MapServer`/`FeatureServer`/`ImageServer`/`SceneServer`/`StreamServer`; other service types are recorded from the catalog walk. Add `--admin-usage` (admin token required) to also read `/admin/usagereports` and `/admin/data/items` for usage-ranked ordering and datastore binding modes — it degrades to a diagnostic if denied. |
| FileGDB (descriptor) | Directory containing `_inventory.json`, or the descriptor file itself | Local filesystem only. |
| FileGDB (workspace) | A local `.gdb` directory | Uses optional `pyogrio`/GDAL read-only metadata calls (`pip install ".[filegdb]"`). Without the extra, the command still exits 0 and records a `partial-coverage` diagnostic. Also available as the `honua_esri_assess.filegdb.scan_filegdb_workspace` library function. |
| RBAC / access | Portal Sharing REST base (`--kind portal`, default) or ArcGIS Server admin URL (`--kind server`) | Writes `EsriAccessFootprint.json` (defaults to stdout). |

Transient upstream failures (`429`, `502`, `503`, `504`) are retried with
capped exponential backoff honoring `Retry-After`; per-endpoint failures
(403, unreachable host, unsupported item type) are downgraded to typed
diagnostics inside the artifact rather than aborting the scan.

## Artifacts and schemas

`EsriFootprint.json` is the sole machine-readable handoff into the closed
Honua migration product; `EsriAccessFootprint.json` is its documented sibling
for identity/RBAC posture. Both are published JSON Schemas (draft 2020-12) in
this repository. Pass `--validate` on scan to check the artifact against the
packaged schema copy before it is written, or run `schema validate <file>` on
any artifact after the fact.

| Artifact | Schema | Reference |
|----------|--------|-----------|
| `EsriFootprint.json` v0.2 | [`schemas/esri-footprint-v0.2.json`](schemas/esri-footprint-v0.2.json) | [v0.1 reference](docs/schemas/esri-footprint.v0.1.md) + [v0.2 delta](docs/schemas/esri-footprint.v0.2.md) (additive: dependency edges, content-type classification, per-layer detail) |
| `EsriAccessFootprint.json` | [`schemas/esri-access-footprint-v0.2.json`](schemas/esri-access-footprint-v0.2.json) | [v0.1 reference](docs/schemas/esri-access-footprint.v0.1.md) |

- Canonical sample footprint: [`docs/samples/esri-footprint.sample.json`](docs/samples/esri-footprint.sample.json)
- Sample readiness report: [`docs/samples/readiness-report.sample.md`](docs/samples/readiness-report.sample.md)
- `honua-caps.json` is produced by `caps` (see [Capability crosswalk](#capability-crosswalk-caps)); it is not yet a published JSON Schema since its crosswalk input is a draft fixture pending honua-io/honua-server#2893.
- Readiness report guide (exit codes, sections, heuristics): [`docs/readiness-report.md`](docs/readiness-report.md)
- Versioning & deprecation policy: [`docs/schemas/versioning.md`](docs/schemas/versioning.md)
- Prospect-facing handoff contract: [`docs/schemas/handoff-contract.md`](docs/schemas/handoff-contract.md)

Artifact `diagnostics[].code` is a locked enum (`rate-limited`,
`partial-coverage`, `missing-permission`, `unresolved-reference`,
`unsupported-item-type`, `redacted-field`) so reviewers can audit exactly what
a diagnostic may say; see the
[diagnostic code catalog](docs/schemas/esri-footprint.v0.1.md#diagnostic-code-catalog).

## Resuming service imports

`honua-migrate services arcgis resume JOB_ID --output result.json` polls an
existing job with GET requests; it never requeues an import. Both numeric and
named GeoServices import statuses are supported using the 2026.1 status contract
(recorded in `response.statusContract`). This is distinct from file-import enums:
GeoServices `8` means Completed and `9` means NeedsReview.

The saved response includes `outcome`, `normalizedStatus`, `terminal`, `timedOut`,
`successful`, `fidelityVerified`, elapsed time and the sanitized server status with
its fidelity findings. Exit 10 means review required, failed/cancelled, unknown
status, or timeout; the receipt is written before exiting. A legacy Completed
response without fidelity metadata may exit zero but has `fidelityVerified=false`.
Do not treat process success alone as proof of full migration fidelity.

Positive `--max-wait` values set a monotonic polling deadline shared by network
timeouts, retries and sleeps. Requests' connect/read timeouts are capped by the
remaining budget; scheduling delays and response-body delivery can still cause
wall time to exceed that budget, and a late observation does not count as success.
`--max-wait 0` takes one status snapshot, bounded by `--timeout-seconds`, without
waiting for a future terminal state. Unknown statuses stop with an explicit
`unknown-status` outcome instead of being guessed or polled indefinitely.

## Target readiness before GeoServices import

`honua-migrate services arcgis preflight` checks the Honua target before a long
import. It sends read-only GETs only: the capability manifest
(`GET /api/v1/capabilities/manifest`) and, after the caller is authenticated,
the import job list. It does not upload a license, change entitlements, or call
`POST .../import/geoservices/start`. `apply` repeats that check and does not
queue a job when the result is failed or unknown. A previous ready result is
not an authorization grant and is not reused after the target, credential, or
declared capability changes.

The CLI reports `unreachable` (including timeout), `unauthenticated`,
`forbidden`, `incompatible-version`, `unavailable-capability`, `unknown`, and
`ready`. Anything other than `ready` exits non-zero with a sanitized reason.
The compatible server contract is capability manifest
`honua.capability_manifest.v1` and API `v1`. Edition names are not a client-side
gate.

Supported customer evaluation is a server with licensing disabled
(`Licensing:Mode=Disabled`). That deployment reports license validation state
`Disabled` and can declare `import.geoservices` available without a signed
license; preflight is ready when the server says the capability is available.
When licensing is enabled, the server decision is authoritative: a valid license
that does not entitle `import.geoservices` is not ready, and an expired or
otherwise invalid license is not ready even if the capability key is present.
This tool will not install a license or invent a paid-tier requirement.

## Python GP run outcomes

`honua-migrate code python run` is target execution. Exit 0 means every
required step reached a successful terminal job and every declared output
reference was checked. An accepted submission, a body with no status, a
skipped call, or `--yes` is not execution success. `--yes` and
`--acknowledge` only authorize a mutating request.

`scan`, `translate`, `pyt`, `atbx`, and `gpservice` are offline assessment.
Their exit 0 does not mean the target ran. `run --dry-run` previews a fully
supported straight-line plan, imports no SDK, and records `outcome` `dry-run`
with `executionSuccess` false. A dry-run of an incomplete plan uses the same
non-success outcome as a live run.

Straight-line literal calls are the only executable shape. Missing required
inputs, non-literal values, results passed through Python names, and calls
inside branches, loops, or nested definitions are refused before any target
request. A known refusal is not dispatched, and a lost, failed, timed-out, or
cancelled response is not posted again.

Live runs poll asynchronous jobs for at most 120 seconds: 120 polls, one
second apart. Timeout, cancellation, and a transport failure after submission
keep the sanitized job id and exit non-zero. Resume that job instead of
starting the plan again while it may still be running. The artifact
`honua.migration.python.gp-run/v1` records the package name and version, the
plan id, and sanitized server and job ids. It does not claim server
attestation. Credentials and URL queries are omitted.

| Exit | Outcome | Reason | Recovery |
|------|---------|--------|----------|
| 0 | `succeeded` | `completed` | No recovery. Declared outputs were verified. |
| 0 | `dry-run` | `not-executed` | Re-run without `--dry-run` and with `--yes` to execute. |
| 2 | `refused` | `syntax-error` | Fix the script. Nothing was submitted. |
| 3 | `incomplete` | `missing-input`, `unresolved-input`, `unsupported-dependency` | Supply literal required inputs and outputs. This runner does not bind prior results. Nothing was submitted. |
| 3 | `unsupported` | `unsupported-control-flow` | Remove branches, loops, and nested definitions. Nothing was submitted. |
| 4 | `unavailable` | `sdk-unavailable` | Install `honua-sdk` in an isolated environment. See the console-script collision guide. |
| 10 | `empty` | `no-runnable-steps` | Nothing to run. Use `scan` or `translate`. |
| 10 | `unsupported` | `unsupported-calls` | Replace unsupported calls. Nothing was submitted. |
| 10 | `partial` | `manual-review-only`, `partial-plan`, `output-unverified`, `submission-not-terminal` | Do not treat a skipped or unverified step as done. |
| 10 | `timed-out` | `job-timed-out` | Keep the job id. Do not start the plan again while that job is unfinished. |
| 10 | `cancelled` | `job-cancelled` | The job id was kept and was not resubmitted. |
| 20 | `failed` | `job-failed`, `remote-error` | Inspect the recorded job id. The request was not retried. |
| 40 |  | safety refusal without `--yes` | Re-run with `--yes` only for a fully supported plan. No artifact is written. |

An invalid server URL still exits 3 with `invalid server URL` and does not
echo the value. Assessment commands use the exit codes in the next section,
not this table.

## Exit codes and failure surface

Assessment commands never print Python tracebacks. Failures surface as typed,
prospect-safe diagnostics on stderr with deterministic exit codes. These codes
are not the Python GP run outcomes above.

| Exit | Meaning |
|------|---------|
| `0` | Success — including partial inventories; per-endpoint failures become `diagnostics[]` entries in the artifact. |
| `1` | Unexpected internal error (`internal-error`); raw exception details are not printed. |
| `2` | Missing/invalid arguments, or report/verdict/caps input handling failed (`report.input.*`). |
| `3` | `report --strict` / `verdict --strict` / `caps --strict` rejected an invalid footprint (`report.schema.invalid`). |
| `4` | Report rendering failed after input parsing succeeded (`report.render.internal`). |
| `5` | `caps --crosswalk` document failed structural or key validation, e.g. an unknown assess-registry key (`report.crosswalk.invalid`). |
| `10`+ | Expected scanner failure (`scanner-error`, `portal.*`, `server.*`); `services arcgis resume` uses `10` for an unsuccessful or unverified terminal observation, with its receipt retained. |
| `20`+ | Could not save the requested output artifact (`output-write-failed`, or output exists without `--force`). |
| `30` | Schema validation failed for `scan --validate` or `schema validate`. |

Local stderr logs can be formatted as text or JSON with `--log-format`; both
stay on the machine running the command. Crash dumps are off by default —
setting `HONUA_ESRI_ASSESS_CRASH_DUMPS=1` allows a local, redacted diagnostic
file under `~/.cache/honua-esri-assess/crashes/` after an internal error.
`--no-network-telemetry-confirm` is an audit-friendly acknowledgement flag; it
is not an opt-in and changes no behavior.

## Development

```bash
python3 -m pip install -e ".[dev]"
pytest                    # full suite
pytest tests/smoke -v     # fixture-backed end-to-end pipeline, no live Esri system
ruff check && mypy
```

The smoke suite exercises the full `scan → EsriFootprint.json → report`
pipeline against checked-in HTTP fixtures and runs as a separate CI job; the
dedicated no-network tests block outbound sockets while scans run. See
[`tests/smoke/fixtures/README.md`](tests/smoke/fixtures/README.md) for the
fixture layout and refresh protocol. Additional developer docs:
[scan handler interface](docs/handler-interface.md) and the read-only
[entitlement enumeration library](docs/entitlements.md)
(`honua_esri_assess.entitlements`).

Esri IP & licensing posture (clean-room formats via GDAL/community readers, no
rehosting of licensed data, no embedded proprietary assets) is documented in
[`docs/compliance/esri-ip-and-licensing-guardrails.md`](docs/compliance/esri-ip-and-licensing-guardrails.md).

Migration implementation ownership, retained SDK/server API boundaries,
release provenance, licensing, and legacy-entry removal gates are defined in
the [ownership and deprecation policy](docs/ownership-and-deprecation.md).
The temporary `honua-sdk` 0.x launcher collision and its fail-closed isolated
invocation path are documented in the
[`honua-migrate` console-script ownership policy](docs/console-script-collision.md).

## Related Honua projects

- [honua-server](https://github.com/honua-io/honua-server) — the flagship multi-protocol geospatial server (GeoServices REST, OGC API, WMS/WFS/WMTS/WCS, STAC, vector tiles, and more) with protocol-level compatibility for selected, operation-scoped Esri client workflows, bounded by its published [compatibility matrix](https://github.com/honua-io/honua-server/blob/trunk/docs/reference/compatibility/geoservices-parity.md) and [certified client envelope](https://github.com/honua-io/honua-server/blob/trunk/docs/gis/CLIENT_CERTIFICATION_ROSTER.md); the migration target this tool sizes.
- [honua-console](https://github.com/honua-io/honua-console) — unified web console (Studio, Catalog, Operate, Share).
- [honua-helm](https://github.com/honua-io/honua-helm) — Helm chart, the Kubernetes deploy path.
- [geobench](https://github.com/honua-io/geobench) — open, vendor-neutral benchmark suite for geospatial servers.

Hosted platform docs: <https://honua.gitbook.io/honuaio/>

## Contributing

Issues and PRs are welcome. Commits follow
[Conventional Commits](https://www.conventionalcommits.org/) (enforced by
commitlint in CI); CI also runs the unit and smoke suites on Python 3.11–3.13
plus `ruff`, `mypy`, and a dependency license guard. Releases go through
release-please and PyPI Trusted Publishing — see [RELEASE.md](RELEASE.md).

## Security

Report vulnerabilities to <security@honua.io>. See the org
[security policy](https://github.com/honua-io/.github/blob/main/SECURITY.md).

## Documentation

- **[Full documentation index](docs/SUMMARY.md)** — every published page, generated from the documentation bundle so it cannot drift.

## License

[Apache-2.0](LICENSE).
