Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### 0.4.0 candidate preparation

- Complete content-free Linux process-denial diagnostics with all-four GID
equality; report missing credentials explicitly and restrict LSM mode output
to known values, preventing arbitrary profile suffix disclosure. Keep ownership
inspection fail-closed and historical denial causality unresolved.
- Reconcile tracked readiness documentation with accepted main PR #81 and closed
issues #61–68; preserve the six unmet issue requirements and bounded next steps.

- Load SPACE's optional SRAI backend only on request or explicit discovery;
default H3 operations no longer import its numerical/ML dependency stack.
Preserve installed dependency failures when SRAI is requested. Measure ANT's
Expand Down
34 changes: 29 additions & 5 deletions GEO-INFER-INTRA/docs/releases/0.4.0_readiness.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
# GEO-INFER 0.4.0 candidate verification

## Modernization verification — 2026-10-08
## Accepted continuation checkpoint — 2026-10-08

Main `fea9f95706e618b61ff9b2cd1e955ef84eae007e` was accepted through
[PR #81](https://github.com/ActiveInferenceInstitute/GEO_INFER/pull/81).
Local canonical eleven-group validation passed with 45 unit suites / 10,883
cases and separate 144+7 ROOT/native cases. Source hash `06e90a509dfd4c55`
binds the independently inspected four figures and 30-page native manuscript.
Whole-output custody verifies identical before/copy/after hashes for 2,038 files.
Fresh independent review accepted source/infrastructure, scientific readability,
output custody and complete candidate/main hosted evidence.

[Same-SHA main CI](https://github.com/ActiveInferenceInstitute/GEO_INFER/actions/runs/37855057244)
passed 22 jobs; Windows, portability, paired GNN and whole-tree formatting also
passed. The main packet contains 32 independently audited raw archives. All 46
coverage dispositions pass; TEST is 2,976/3,383 lines (87.9693%) against 85%.
Each interpreter verifies 45 installed wheels, 45 base imports and 20 operation
profiles outside checkout. Real PostGIS/Redis/MinIO operations and signed DuckDB
extensions pass. GNN pin `9255e19f951d4c9c1461514464d420bd3fc8b912` has actual
four-family/exporter/replay evidence; it was reviewed through PR #79.
All required readiness issues #61–68 are closed. The six remaining scopes and
bounded next steps are in the [issue ledger](issue_reconciliation_2026_10.md).
These receipts prove this checkpoint; subsequent source changes require renewal.

## Historical modernization verification — 2026-10-08

The modernization implementation is verified at clean candidate
`b3a5ed2f457bd7658172d017472533b3e094ea35`. All 21 jobs in
Expand Down Expand Up @@ -37,17 +60,18 @@ ancestry check and actual same-SHA main-triggered evidence. Its outcome is
recorded in [PR #80](https://github.com/ActiveInferenceInstitute/GEO_INFER/pull/80)
and [issue #68](https://github.com/ActiveInferenceInstitute/GEO_INFER/issues/68).
Hardware, licensed data, historical failure attribution, configured advisor
access, current-source scientific review and release publication retain their
access, release publication retain their
separate unmet requirements in the [issue ledger](issue_reconciliation_2026_10.md).

## Continuation acceptance
## Historical continuation preparation

The reviewed modernization was published at `42d2964b4` through PR #80.
Independent review subsequently inspected all four current figures and all 35
native manuscript pages, checking counts, formulas and readability against the
owning implementations. This meets the scientific inspection component for that
bundle. DATA corrections and the new disposable service lane require renewed
source-bound producer, render, wheel and hosted evidence. Historical output
bundle. DATA corrections and the new disposable service lane subsequently received
renewed source-bound producer, render, wheel and hosted evidence at fea9f9570,
as recorded above. Historical output
byte custody preserves failed evidence; it does not require scientific acceptance
of every historical file.

Expand Down
73 changes: 55 additions & 18 deletions GEO-INFER-INTRA/docs/releases/issue_reconciliation_2026_10.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,72 @@ integration into main. Closing an issue means its actual requirements are met;
the owner explicitly requested that unmet issues remain open. Deferral does
not constitute technical acceptance.

Main `42d2964b4a3919f3865b2b41a69acbe100b97c7c` incorporated the reviewed
modernization through [PR #80](https://github.com/ActiveInferenceInstitute/GEO_INFER/pull/80),
preserving the accepted GNN 4.1.0 ancestry. Its same-SHA main CI and supplementary
checks, local full-eleven producer, all-45-wheel inventories and independent
source/hosted/output-custody review passed. Evidence remains bound to that revision.
Accepted main `fea9f95706e618b61ff9b2cd1e955ef84eae007e` incorporated the DATA and
disposable-service continuation through [PR #81](https://github.com/ActiveInferenceInstitute/GEO_INFER/pull/81).
It preserves the PR #80 modernization and accepted GNN 4.1.0 ancestry. Local
full-eleven verification, 45 unit suites / 10,883 cases, 144+7 ROOT/native tests,
30-page manuscript/four-figure scientific inspection and fresh independent
source, hosted-artifact and whole-output custody reviews passed.
[Main CI](https://github.com/ActiveInferenceInstitute/GEO_INFER/actions/runs/37855057244)
passed all 22 jobs. Supplementary Windows, portability, paired GNN and whole-tree
formatting workflows passed. All 32 raw main archives and all 46 coverage
dispositions were audited; TEST measured 2,976/3,383 lines (87.9693%). Evidence
is specific to this accepted checkpoint; a later patch needs fresh gates.

A subsequent DATA review found PostgreSQL routing/indexing defects and spatial
row-identity defects. The continuation corrects them and adds a disposable hosted
service lane. Its focused tests and independent source review pass; final local,
installed-wheel, native and hosted evidence must be renewed before integration.
The current follow-up adds GID equality and restricts Linux denial LSM modes to
known values. It reconciles the tracked ledger with completed readiness issues.
Implementation does not identify the historical denied-task class; #78 remains
open pending actual reproduction and causal evidence.

| Issue | Verified work / evidence | Remaining acceptance |
| --- | --- | --- |
| #58 (closed) | MATH circulation/skew/Hodge APIs and analytical oracles were integrated through PR #80. | External formal-repository bridge edits are separate scope. |
| #61 | Published main has reviewed source and hosted evidence. | Renew acceptance for the DATA continuation and complete required children. |
| #62 | Retained timing separates actual child completion from census; demonstrated census-error propagation is fixed without budget changes or retries. | Renew complete TEST and independent evidence. Conclusive historical environmental attribution is not an additional criterion; its UNKNOWN status remains retained. |
| #63 | Main TEST measures 2,977/3,383 lines (87.9988%) against the unchanged 85% floor; all 46 dispositions audited. | Renew final-candidate measurement and complete #62. |
| #64 | Main strict/analytical and full-eleven gates pass. | Renew gates for changed source. Earlier failures remain diagnostic evidence. |
| #65 | Independent review exposed and verified corrections for PostgreSQL routing/indexing and H3/R-tree observation identity. | Real PostGIS/Redis/MinIO/S3-compatible service operations, fresh two-interpreter wheels/profiles and pinned paired interchange must pass on the final revision. |
| #66 | Independent scientific/readability review passed all four current figures and the actual 35-page native manuscript at main/source hash 7d76fd470a2bec35. | Renew producer, native render, source/receipt/figure/model provenance, generated docs/index, ROOT tests and whole-output byte snapshot for changed source. Historical output files are retained evidence; scientific acceptance of every historical file is not an issue criterion. |
| #67 | Main CI and supplementary artifacts received fresh independent archive/receipt audits. | Renew exact-candidate hosted artifacts, including the new service lane. |
| #68 | Ordinary main integration at 42d2964b4 is verified. | Integrate the new reviewed candidate ordinarily and verify same-SHA main results. |
| #61 (closed) | Exact-main readiness and all required children accepted. | Hardware, data, historical causality, advisor and release scopes remain separate. |
| #62 (closed) | Real ownership/cleanup/receipt cases and independent infrastructure review accepted. | Historical environmental attribution remains UNKNOWN and is tracked separately. |
| #63 (closed) | All 46 coverage dispositions audited; TEST 87.9693% exceeds its unchanged 85% floor. | Renew measurement for later source changes. |
| #64 (closed) | Strict/analytical, security, reproducibility and full-eleven gates accepted. | Retain failures and renew appropriate gates for later changes. |
| #65 (closed) | 45 installed wheels, 45 base imports and 20 operation profiles per interpreter; real PostGIS/Redis/MinIO operations and pinned four-family GNN evidence accepted. | Real-service evidence is S3-compatible local CI, not live AWS acceptance. |
| #66 (closed) | Source hash 06e90a509dfd4c55: eleven-group producer, 144+7 ROOT/native cases, all four figures/30 native pages, generated docs/index and 2,038-file whole-output snapshot accepted. | Scientific review covers the current bundle; historical failed outputs remain preserved. |
| #67 (closed) | Exact-candidate and fresh same-SHA main hosted packets independently accepted. | Main packet comprises 32 raw archives; default-seven hosted producer evidence remains distinct from local eleven-group evidence. |
| #68 (closed) | Ordinary fast-forward to fea9f9570 through PR #81; local/API/remote parity verified. | Retain rollback checkpoint 42d2964b4; later changes need a new review and publication audit. |
| #69 | Local diagnostics report no usable CuPy, Torch CUDA or JAX GPU backend; CPU operation preserved. | Supported physical hardware and precision/parity/timing/memory evidence. |
| #70 | Captured layers and replay preserved. | Complete bioregion acquisition needs a declared source, license, extent and resource budget. |
| #72 | Original PROJ I/O evidence and negative lock/content fault controls retained. | Historical cause remains UNKNOWN; successful CRS tests do not explain it. |
| #73 | Native independent review is available and used. | Actual configured advisor review requires account-level remedy; native review does not substitute for that named service. |
| #74 | Version parity remains 0.4.0. | Explicit release/version decision after readiness, then specifically authorized tag/assets/registry publication and destination verification. |
| #78 | Fail-closed owned-process observation retains content-free Linux denial facts. | Identify the historical live-task denial class; a nonrecurrence is not identification. |
| #78 | Fail-closed owned-process observation retains content-free Linux denial facts; this follow-up completes GID equality and prevents arbitrary LSM suffix disclosure. | Identify the historical live-task denial class; a nonrecurrence is not identification. |

Completed implementation, hosted receipts, historical failed attempts and
unmet acceptance criteria must remain distinguishable. Public issue comments
must not include private host inventories, credentials or conversation artifacts.

## Bounded next steps for open issues

- **#69:** retain CPU operation while the owner holds GPU experiments. A future
backend must work from the Mac target and meet the float64 contract on actual
physical hardware before parity, chunk/failure, memory and timing acceptance.
- **#70:** choose the full boundary source/license/extent first; then acquire
immutable source bytes, record attribution/checksums and verify WGS84 geometry,
stable identities and real integration/rendering. Captured partial layers do
not satisfy the complete bioregion requirement.
- **#72:** obtain a bounded reproduction or recurrence containing the actual
loaded library versions, import order, database checksum/integrity and I/O
failure class. Prior lock and content-fault controls were negative; rerunning
clean stress suites does not establish the historical cause.
- **#73:** the account owner resolves configured-advisor availability. Bind an
actual successful review to a stable candidate and address its findings.
Native independent review provides a separate review lane.
- **#74:** after an explicit version/release decision, create an annotated
`v0.4.0` tag at the then-accepted main SHA; require tag-specific same-SHA CI
and release gates, then publish the GitHub release with all 45 wheel assets
and the manuscript PDF. Verify destination checksums and versions and retain
the previous accepted main as rollback evidence. The current workflow uploads
wheels as a CI artifact and attaches assets only when a release object exists; it
does not publish to PyPI. Registry publication needs a named destination and
its separate decision. Check tag/release existence immediately before acting.
- **#78:** capture only kernel state/flags, credential equality, environment-file
ownership and security-mode flags at a real denial. Missing GID fields or
platform credentials report `unavailable`; arbitrary profile suffixes report
generic confinement. Preserve the 50 ms observation and fail-closed ownership
decision. Exclude a class only after a positive kernel observation proves it
cannot remain an owned live process.
18 changes: 16 additions & 2 deletions GEO-INFER-TEST/src/geo_infer_test/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ def _kernel_exiting(pid: int) -> bool | None:
return _stat_reports_exiting(text)


def _kernel_denial_facts(pid: int, *, uid: int | None = None) -> str | None:
def _kernel_denial_facts(
pid: int, *, uid: int | None = None, gid: int | None = None
) -> str | None:
"""Summarize why ``pid``'s environment may be denied, without its content.

Only kernel state is reported: run state and flags, whether procfs made
Expand All @@ -91,6 +93,9 @@ def _kernel_denial_facts(pid: int, *, uid: int | None = None) -> str | None:
if getuid is None:
return None
uid = getuid()
if gid is None:
getgid = getattr(os, "getgid", None)
gid = getgid() if getgid is not None else None
task = _PROCFS / str(pid)
try:
stat = (task / "stat").read_text(encoding="latin-1")
Expand All @@ -108,11 +113,20 @@ def _kernel_denial_facts(pid: int, *, uid: int | None = None) -> str | None:
else:
owner_fact = "self" if owner == uid else str(owner)
uids = lines.get("Uid", "").split()
gids = lines.get("Gid", "").split()
gid_match = (
str(all(value == str(gid) for value in gids))
if gid is not None
and len(gids) == 4
and all(value.isdecimal() for value in gids)
else "unavailable"
)
facts = [
f"state={fields[0]}",
f"flags={int(fields[6]):#x}",
f"environ_owner={owner_fact}",
f"uid_match={bool(uids) and all(value == str(uid) for value in uids)}",
f"gid_match={gid_match}",
]
for key, label in (
("Threads", "threads"),
Expand All @@ -132,7 +146,7 @@ def _kernel_denial_facts(pid: int, *, uid: int | None = None) -> str | None:
"lsm=unconfined"
if label_text == "unconfined"
else f"lsm=confined({mode})"
if mode.isalpha()
if mode in {"enforce", "complain", "kill"}
else "lsm=confined"
)
return " ".join(facts)
Expand Down
64 changes: 61 additions & 3 deletions GEO-INFER-TEST/tests/unit/test_process_ownership_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,15 +580,16 @@ def test_denial_facts_are_content_free_kernel_observations(tmp_path, monkeypatch
status=(
"Name:\tPRIVATE_NAME\n"
"Uid:\t1000\t1000\t1000\t1000\n"
"Gid:\t1000\t1000\t1000\t1000\n"
"Threads:\t3\nNoNewPrivs:\t0\nSeccomp:\t2\n"
),
attr="/usr/bin/PRIVATE_PROFILE (enforce)\n",
)
owner = os.stat(task / "environ").st_uid
facts = module._kernel_denial_facts(4321, uid=owner)
facts = module._kernel_denial_facts(4321, uid=owner, gid=1000)
assert facts == (
"state=R flags=0x400100 environ_owner=self "
f"uid_match={owner == 1000} "
f"uid_match={owner == 1000} gid_match=True "
"threads=3 no_new_privs=0 seccomp=2 lsm=confined(enforce)"
)
assert "PRIVATE" not in facts
Expand All @@ -610,7 +611,7 @@ def test_denial_facts_report_foreign_environ_owner_and_unconfined(
facts = module._kernel_denial_facts(4321, uid=owner + 1)
assert facts == (
f"state=R flags=0x4 environ_owner={owner} uid_match={owner + 1 == 7} "
"lsm=unconfined"
"gid_match=unavailable lsm=unconfined"
)


Expand Down Expand Up @@ -647,3 +648,60 @@ def facts(pid):
# Observed at the denial, before a short-lived task can disappear.
assert observed_at == [0.0]
assert "PRIVATE" not in str(error)


@pytest.mark.parametrize(
("gids", "expected"),
[
("7 7 7 7", "True"),
("7 7 8 7", "False"),
("7 7 7", "unavailable"),
("7 7 invalid 7", "unavailable"),
("", "unavailable"),
],
)
def test_denial_gid_equality_requires_all_four_kernel_credentials(
tmp_path, monkeypatch, gids, expected
):
monkeypatch.undo()
monkeypatch.setattr(module, "_PROCFS", tmp_path)
_fake_task(
tmp_path,
4321,
stat=_stat_line(comm="private", flags=0),
status=f"Gid: {gids}\n",
)
facts = module._kernel_denial_facts(4321, uid=7, gid=7)
assert f"gid_match={expected}" in facts
assert "invalid" not in facts


@pytest.mark.parametrize("mode", ["PRIVATEPROFILE", "enforce)secret", "", "audit"])
def test_denial_lsm_suffix_cannot_disclose_arbitrary_profile_text(
tmp_path, monkeypatch, mode
):
monkeypatch.undo()
monkeypatch.setattr(module, "_PROCFS", tmp_path)
_fake_task(
tmp_path,
4321,
stat=_stat_line(comm="private", flags=0),
status="",
attr=f"PRIVATE_PROFILE ({mode})\n",
)
facts = module._kernel_denial_facts(4321, uid=7, gid=7)
assert facts.endswith("lsm=confined")
assert "PRIVATE" not in facts


def test_denial_gid_without_platform_credentials_is_unavailable(tmp_path, monkeypatch):
monkeypatch.undo()
monkeypatch.setattr(module, "_PROCFS", tmp_path)
monkeypatch.setattr(module, "os", SimpleNamespace(stat=os.stat))
_fake_task(
tmp_path,
4321,
stat=_stat_line(comm="private", flags=0),
status="Gid: 7 7 7 7\n",
)
assert "gid_match=unavailable" in module._kernel_denial_facts(4321, uid=7)
Loading
Loading