Skip to main content

mini-atlas-api-flask-python

Source of the mini-atlas-monitor distribution. The Python import package remains mini_atlas_api. The console command is mini-atlas. One Waitress process serves the read-only HTTP API and, when the release assets are installed, the compiled React application.

Pass 1 (current)

The HTTP API is a read-only monitor. User Python creates projects and runs through the simulator library (create_project, start_run). The HTTP monitor does not create projects, runs, or initialize a missing result store. Reading an existing SQLite catalog may create SQLite WAL/SHM sidecar files.

  • Application factory (create_app) with required RESULT_STORE configuration
  • GET /api/v1/projects — list projects (ResultReader.list_projects), including run_count
  • GET /api/v1/projects/{project_id}/runs — paginated run list (ResultReader.list_runs), including description, committed_steps, scheduled_steps, and summary declaration metadata
  • GET /api/v1/runs/{run_id} — run detail (ResultReader.get_run), including description when recorded
  • GET /api/v1/runs/{run_id}/lineage — declared Lineage stages (ResultReader.list_lineage_stages)
  • GET /api/v1/runs/{run_id}/lineage-observations — selected-step Lineage observations (ResultReader.read_lineage_at_step)
  • GET /api/v1/cursor — latest store-wide commit_id (ResultReader.latest_cursor)
  • GET /api/v1/updates — committed-step update polling (ResultReader.get_updates)
  • GET /api/v1/runs/{run_id}/steps — committed steps at a frozen cursor (ResultReader.list_committed_steps)
  • GET /api/v1/runs/{run_id}/progress — run progress at a frozen cursor (ResultReader.run_progress)
  • GET /api/v1/runs/{run_id}/metric-definitions — declared metric metadata (ResultReader.list_metric_definitions)
  • GET /api/v1/runs/{run_id}/metrics — snapshot-pinned metric series and optional selected-step values (ResultReader.read_metrics)
  • GET /api/v1/runs/{run_id}/streams — declared streams and selected-step counts (ResultReader.list_streams)
  • GET /api/v1/runs/{run_id}/streams/{stream_name}/rows — bounded selected-step table page (ResultReader.read_table)
  • Waitress entry point (run.py)
  • Local Swagger UI (no CDN)

Known resources reject POST, PUT, PATCH, and DELETE with HTTP 405, Content-Type: application/json, and {"message": "The method is not allowed for the requested URL."}. Allow lists the framework methods for that resource (GET, HEAD, and OPTIONS where the framework provides them) and does not advertise POST, PUT, PATCH, or DELETE. An unknown /api path stays the framework HTML 404. That 404 is not the React document and is not this JSON 405 body.

GET /api/v1/projects keeps three distinct store cases. A missing configured path returns {"projects": []} and does not create the path. An empty directory returns the same empty envelope and does not create a catalog. A corrupt nonempty store returns HTTP 503 with {"message": "The configured result store could not be read."}.

Store cursor is global publication order (latest committed commit_id), not simulated time. Clients poll /updates every 1–2 seconds; there is no server long-poll, SSE, or WebSockets. The API does not accept or return a client generation token.

Dependencies

Runtime dependencies are declared in pyproject.toml:

  • Python >=3.10
  • mini-atlas-simulator>=0.2.0,<0.3
  • Flask>=3.0,<4
  • Flask-RESTX>=1.3,<2
  • waitress>=3.0,<4

Development installs use the project metadata (requirements-dev.txt). Install a local simulator wheel or checkout first. The simulator package is not published on PyPI. requirements.txt repeats the HTTP server ranges for the current image install and does not install the simulator.

Supported versions

  • Python 3.10+ (developed and tested on 3.13 in this checkout).
  • Waitress is the HTTP server (not Flask’s debug server).

Install the monitor

Install a locally built simulator wheel, then the monitor wheel:

python3 -m venv .venv
.venv/bin/python -m pip install /path/to/mini_atlas_simulator-0.2.0-py3-none-any.whl
.venv/bin/python -m pip install /path/to/mini_atlas_monitor-0.2.0-py3-none-any.whl

The installed command serves the API and the compiled UI on one origin. It does not run Node, npm, Vite, or nginx.

mini-atlas --store /absolute/path/to/result-store --host 127.0.0.1 --port 8080 --no-browser

--store selects the result store and overrides RESULT_STORE. When --store is omitted, RESULT_STORE is the fallback. The default bind is 127.0.0.1 and the default port is 8080. The default opens a browser after the socket binds. --no-browser skips that. mini-atlas --help exits 0 and does not start the server.

A missing store path, or a path that is a file, exits 2 and creates nothing. An existing directory is accepted, including an empty directory. Binding 0.0.0.0 or :: prints a warning: the process is unauthenticated and belongs on a trusted network or behind an authenticating proxy. The browser URL for 0.0.0.0 is http://127.0.0.1:<port>/. The browser URL for :: is http://[::1]:<port>/. This package does not add authentication. Keyboard interrupt prints Shutting down. and exits 0.

The monitor and the API are served at the origin root. /assets/... and /api/v1/... are paths from that root. Hosting the application under a path prefix is not supported.

An unknown /api route stays the framework HTML 404 and is never the React document. This package does not convert that 404 to JSON. /swagger/ remains the Flask-RESTX UI, and /api/v1/swagger.json remains JSON. GET /api/v1/meta reports the installed monitor distribution, monitor version, simulator version, UI commit, and UI version. It does not open the store.

JSON gzip

mini-atlas and run.py negotiate gzip for eligible JSON through a standard-library WSGI middleware attached once before Waitress starts. The metric response schema is unchanged: the same JSON bytes are sent, optionally gzip-encoded on the wire.

Compression applies only when the response Content-Type is application/json (an optional charset is allowed), the uncompressed body is at least 1,024 bytes, the body is not already encoded, and the request accepts gzip with a positive quality value. HTML, JavaScript, CSS, images, fonts, static assets, the React SPA shell, and the Swagger UI page are not compressed. Large application/json responses such as /api/v1/swagger.json or metric reads follow the same JSON rule. Clients that omit Accept-Encoding or send identity receive the same JSON bytes as before. Eligible responses that can vary by encoding include Vary: Accept-Encoding. HEAD is not gzip-encoded: Flask has already discarded the body, so HEAD keeps the application's identity Content-Length and an empty body. GET of the same JSON resource may still negotiate gzip.

Opening a catalog for a read can create catalog.sqlite-wal and catalog.sqlite-shm beside the catalog when the directory is writable. Those sidecars are SQLite files. They are not projects, runs, or result files.

Frontend assets

The compiled React application is vendored from a pinned mini-atlas-webapp commit before python -m build. Node is required only for that release build, and only at a version matching the webapp engines range (>=24 <25). Vite remains the UI development server. Unit tests and pip install of a built wheel do not run Node.

From the pinned webapp commit:

npm ci
npm run build

From this repository:

python scripts/vendor_frontend.py \
  --dist /absolute/path/to/mini-atlas-webapp/dist \
  --commit <40-hex webapp commit> \
  --version <webapp package.json version> \
  --built-at <ISO-8601 commit timestamp>
python -m pip install build
python -m build

The wheel and sdist contain those bytes and ui_provenance.json. Rebuilding a wheel from that sdist does not run Node and does not need a webapp checkout. python -m build fails if mini_atlas_api/web/index.html or the provenance manifest is missing or inconsistent. When those assets are absent, run.py and the test client stay API-only.

Development checkout

python3 -m venv .venv
.venv/bin/python -m pip install /path/to/mini-atlas-simulator
.venv/bin/python -m pip install -r requirements-dev.txt

Use a local mini-atlas-simulator checkout or wheel. Do not rely on PyPI for the simulator package.

Result store

Choose an empty directory on the host (for example /path/to/result-store). User Python writes catalog and Parquet data there through the simulator library. HTTP requests do not create projects or store artifacts. Known-resource mutation methods return the JSON 405 described above. Missing, empty, and corrupt stores stay distinct on GET.

Run the API (native, Waitress)

.venv/bin/python run.py --store /path/to/result-store

Or set RESULT_STORE and omit --store:

export RESULT_STORE=/path/to/result-store
.venv/bin/python run.py --host 127.0.0.1 --port 8080

Optional: --host (default 127.0.0.1), --port (default 8080). Bind 0.0.0.0 only when you intend to expose the API on the network (containers use 0.0.0.0 internally).

Flask works without the React app. Point a browser or curl at http://127.0.0.1:8080/api/v1/cursor or /swagger/ to verify.

Production container (local)

Build from this repository with the simulator supplied as a narrow additional build context (see Dockerfile). The image builds mini-atlas-simulator and mini-atlas-monitor wheels from that context and the committed vendored UI, installs them with pip, and runs the installed mini-atlas command. The runtime image does not contain Flask or simulator source checkouts, Node, npm, or nginx.

Item Required Meaning
Store path (CLI) Yes --store /data/store in the image command
Host bind mount Yes (Compose) Set MINI_ATLAS_RESULT_STORE to an absolute host directory before docker compose up in mini-atlas-webapp
Mount mode Read-write SQLite may create catalog.sqlite-wal and catalog.sqlite-shm beside the catalog on first open. A fresh read-only bind mount can return 503 until sidecars exist; do not treat :ro as fully supported for a new store.
Container user uid 10001 The host directory must be readable and writable by uid 10001 (or group-accessible with the same effective permissions).

Health check: GET /api/v1/cursor (returns {"latest_cursor": 0} on an empty store).

docker build -f Dockerfile \
  --build-context simulator=/path/to/mini-atlas-simulator \
  -t mini-atlas-monitor:local .

Compose (from mini-atlas-webapp): one monitor service, 127.0.0.1:8080 only. Deployers may place their own reverse proxy in front of the image; nginx is not part of the product runtime.

Tests

PYTHONDONTWRITEBYTECODE=1 .venv/bin/python -m pytest -p no:cacheprovider

Run list query parameters

GET /api/v1/projects/{project_id}/runs accepts optional:

  • q — run name substring
  • status — pending, running, completed, or failed
  • sort_by + sort_dir — both required together; columns name, status, wall_start, run_id; directions asc or desc (omit both for reader default: wall_start desc, then run_id asc)
  • limit (1–1000, default 50) and offset (default 0)
  • repeated summary — metric definition_ids for optional row summaries

Example:

GET /api/v1/projects/01J.../runs?limit=50&offset=0&summary=yield&summary=precision

Response envelope:

{
  "observed_cursor": 40,
  "page": {"limit": 50, "offset": 0, "next_offset": null, "returned": 1, "matched_rows": 1},
  "runs": []
}

Each project row may include run_count. Each run row may include description, committed_steps, and scheduled_steps. Each requested summary item may include declared, label, unit, grain, and display. Flask copies those public reader fields and does not calculate them. Missing, logged-null, explicit zero, and undeclared summaries stay distinct.

Run detail:

GET /api/v1/runs/01J...

Run detail may include description (null when the run has none).

Store cursor and update polling

GET /api/v1/cursor
{"latest_cursor": 12}

Missing or empty store directories return {"latest_cursor": 0} without creating storage.

GET /api/v1/updates?after_cursor=0&limit=100

Optional query parameters:

  • after_cursor — last applied store commit_id (defaults to 0 when omitted; must be >= 0)
  • limit — page size 1–1000 (default 100)
  • repeated run_ids — optional ULID filter

Response envelope (matches ResultReader.get_updates):

{
  "after_cursor": 0,
  "through_cursor": 2,
  "latest_cursor": 5,
  "commits": [
    {"commit_id": 1, "run_id": "01J...", "step_n": 1, "as_of": "2025-01-01T00:00:00Z"}
  ]
}

through_cursor is the safe next poll cursor (last commit_id returned on this page). latest_cursor is the observed store head and may be greater than through_cursor when the page is truncated by limit. Invalid or future cursors return HTTP 400 and are never clamped.

Committed steps and progress (frozen cursor)

GET /api/v1/runs/01J.../steps?through_cursor=12
GET /api/v1/runs/01J.../progress?through_cursor=12
GET /api/v1/runs/01J.../progress?through_cursor=12&step_n=3

through_cursor is required. Optional step_n selects an exact committed step; when omitted, progress uses the reader default (latest committed step at that cursor).

Steps envelope:

{
  "run_id": "01J...",
  "through_cursor": 12,
  "steps": [{"step_n": 1, "as_of": "2025-01-01T00:00:00Z", "commit_id": 1}]
}

Progress envelope (from ResultReader.run_progress):

{
  "run_id": "01J...",
  "through_cursor": 12,
  "scheduled_steps": 600,
  "committed_steps": 3,
  "step_n": 3,
  "as_of": "2025-01-03T00:00:00Z",
  "commit_id": 8
}

Zero committed steps return HTTP 200 with steps: [] or null progress fields; step 1 is never invented.

Metric definitions and reads (frozen cursor)

GET /api/v1/runs/01J.../metric-definitions
GET /api/v1/runs/01J.../metrics?through_cursor=12&definition_id=metric_a&definition_id=metric_b
GET /api/v1/runs/01J.../metrics?through_cursor=12&step_n=5&definition_id=metric_a

through_cursor is required on metric reads and freezes the publication snapshot. Optional repeated definition_id selects metrics; when omitted, the reader returns all declared metrics in deterministic definition_id order. Optional step_n selects committed-step card values; when supplied it must be committed at through_cursor. Series points may still include steps after the selected step when they are committed at the frozen cursor.

Metric values are logged facts from user Python. Flask does not compute coverage, percentages, cumulative totals, or chart ranges. Missing points are not coerced to zero. display.format=percent is presentation metadata only (stored ratios such as 0.099 stay numeric). chart_range and response generation are client-owned; this API does not accept them.

Definitions envelope:

{
  "run_id": "01J...",
  "definitions": [
    {
      "definition_id": "slice_node_count",
      "label": "Slice nodes",
      "unit": "count",
      "grain": "per_step",
      "direction": "none",
      "series": {"group": "graph_asof", "role": "member"}
    }
  ]
}

Metric read envelope (matches ResultReader.read_metrics / MetricRead):

{
  "run_id": "01J...",
  "through_cursor": 12,
  "step_n": 5,
  "definitions": [],
  "values": [],
  "series": {}
}

When step_n is omitted, values is empty and step_n is null. Zero-commit runs may still expose declared definitions; metric series and values are empty until steps commit.

Stream discovery and table pages (frozen cursor, one step)

GET /api/v1/runs/01J.../streams?through_cursor=12&step_n=5
GET /api/v1/runs/01J.../streams/subject_scores/rows?through_cursor=12&step_n=5&limit=100&offset=0

through_cursor and step_n are required on both endpoints. They pin the publication snapshot and select exactly one committed step. Invalid or uncommitted step_n returns HTTP 400 and is never clamped to nearest or latest. There is no from_n/to_n, cross-step history, subject history, or show-all mode.

Stream list (ResultReader.list_streams):

{
  "run_id": "01J...",
  "through_cursor": 12,
  "step_n": 5,
  "as_of": "2025-01-06T00:00:00Z",
  "streams": [
    {
      "name": "subject_scores",
      "schema_version": 1,
      "role": "scores",
      "subject_column": "subject_id",
      "selection": "all",
      "tiebreak_columns": ["subject_id"],
      "logged_rows": 400,
      "coverage": {"status": "ok"},
      "declaration_coverage": {"scope": "dataset"}
    }
  ]
}

Per-stream coverage.status at the selected step is one of ok, not_recorded, or logged_empty (table rows use additional statuses below). Declared stream metadata comes from user Python; roles are generic hints only.

Table page query parameters:

Parameter Required Meaning
through_cursor yes Frozen store commit_id
step_n yes Committed step for this page
limit no Page size (reader default 100, maximum 10000)
offset no Row offset (default 0)
sort no Repeatable column:asc or column:desc (user sort first; reader applies declared tie-breaks then _row_id ASC)
filter no Repeatable structured filter (see below)

Filter wire syntax (maps to ResultReader.read_table filter= tuples):

  • column:is_null or column:is_not_null
  • column:op:json_value for all other operators

Supported operators: eq, ne, lt, le, gt, ge, in, not_in, contains, is_null, is_not_null. The JSON value must be valid JSON (true, false, numbers, strings in quotes, arrays for in/not_in). Malformed entries, unknown operators, unknown columns, and invalid filter or query input, including type mismatches, return HTTP 400. Missing, corrupt, or unreadable result data returns HTTP 503 with the store-unreadable message. Unexpected server failures return HTTP 500.

Examples:

GET .../rows?through_cursor=12&step_n=5&sort=score:desc&filter=flagged:eq:true&filter=score:ge:0.5
GET .../rows?through_cursor=12&step_n=5&filter=subject_id:in:["A-1","A-2"]
GET .../rows?through_cursor=12&step_n=5&filter=note:is_null

Table page envelope (TablePage):

{
  "stream": "subject_scores",
  "run_id": "01J...",
  "through_cursor": 12,
  "step_n": 5,
  "page": {
    "limit": 100,
    "offset": 0,
    "next_offset": 100,
    "returned": 100,
    "logged_rows": 400,
    "matched_rows": 400
  },
  "coverage": {
    "status": "ok",
    "steps_not_recorded": [],
    "steps_logged_empty": []
  },
  "columns": [{"name": "_row_id", "type": "int64"}],
  "rows": [{"_row_id": 1, "_step_id": 5, "_as_of": "2025-01-06T00:00:00Z", "score": 0.91}]
}

Row coverage.status meanings:

Status Meaning
ok Matching rows returned (or metadata-only success)
not_recorded Stream not logged at this step; rows empty
logged_empty Writer logged a zero-row table; logged_rows is 0
filtered_empty Stored rows exist but filter matched none (logged_rows > 0, matched_rows = 0)
page_past_end Matches exist but offset >= matched_rows; next_offset is null

Arbitrary user columns are returned as JSON objects in rows (not a fixed score schema). Integers with magnitude >= 2^53 serialize as decimal strings; smaller integers stay JSON numbers. Booleans stay booleans; null stays null; UTC timestamps end in Z. Non-finite floats are not emitted.

stream_name must be a safe declared name (alphanumeric start; [A-Za-z0-9._-]; no slashes or traversal). Unknown undeclared streams return HTTP 400 from the reader. Missing configured store paths return HTTP 404 for syntactically valid unknown runs without creating artifacts; corrupt stores return HTTP 503.

Client stale-response generation is not an API field.

Rule Foundation and first-class decision reads

These are read-only HTTP projections of the committed simulator public APIs. The API does not execute rule or decision logic, verify logic_ref, compute counts, infer set overlap, populate evaluated subjects, or promote a legacy generic role=decisions stream that has no first-class target declaration. There is no React or Dash Rules tab in this repository.

Routes

  • GET /api/v1/runs/{run_id}/rules lists declarations at any commit state, including zero-commit runs. It has no accepted query parameters and returns {"run_id": "...", "definitions": [...]}. Each definition preserves rule_id, label, description, version, target namespace, parameters, claimed logic_ref, optional category/tags, and the definition_fingerprint.
  • GET /api/v1/runs/{run_id}/rule-aggregates requires through_cursor (nonnegative) and step_n (positive and committed at that cursor). Repeat rule_id to select rules; omit it for every declared rule. The reader preserves logged zero, null individual measures, and missing aggregates (logged: false).
  • GET /api/v1/runs/{run_id}/rule-aggregate-series requires through_cursor, explicit positive from_n and to_n, one or more repeatable rule_id values, and one or more repeatable field values. The simulator enforces the maximum span and series count. chart_range, generation, show_all, and implicit latest-step selection are rejected.
  • GET /api/v1/runs/{run_id}/rule-set-aggregates requires through_cursor and step_n. It returns the user-logged intersection, union, and ordered difference records without Flask arithmetic or inference.
  • GET /api/v1/runs/{run_id}/rules/{rule_id}/evidence-status requires through_cursor and step_n. Its authoritative status is not_recorded, logged_empty, or recorded. rule_id is an opaque identifier and may contain /, including a trailing slash or an embedded //. Percent-encode each slash as %2F. The value is not a filesystem path. A rule id that begins with / is not representable: routing merges that empty segment and redirects to the id without the leading slash.
  • GET /api/v1/runs/{run_id}/rules/{rule_id}/evidence is the dedicated bounded one-rule evidence page. It requires through_cursor and step_n; optional limit is 1–1000 (default 100), offset is nonnegative, and repeatable sort=column:asc|desc and structured filter values are supported. The route always supplies exactly one rule_id equality predicate to the simulator read_table reader. Extra rule_id filters, arbitrary stream names, show_all, generation, and chart_range are rejected. Page statuses are ok, filtered_empty, page_past_end, logged_empty, and not_recorded.
  • GET /api/v1/runs/{run_id}/decision-target returns {"run_id": "...", "decision_target": null} when no first-class target exists, or the declared target metadata when it does. It has no accepted query parameters and works before the first commit.
  • GET /api/v1/runs/{run_id}/decision-status requires through_cursor and step_n, returning the authoritative not_recorded/logged_empty/recorded receipt status.
  • GET /api/v1/runs/{run_id}/decisions/rows requires through_cursor and step_n; it accepts the same bounded limit (default 100, maximum 1000), offset, repeatable sort, and structured filter parameters as table pages. It uses the declared first-class decision stream only and calls the simulator read_table reader. Legacy decision-role streams without a target are returned as an empty, not_recorded decision page.

All structured filters use column:op:json_value; null checks use column:is_null or column:is_not_null. Operators are eq, ne, lt, le, gt, ge, in, not_in, contains, is_null, and is_not_null. Sort/filter columns must be safe identifiers. Singular values cannot be repeated; rule IDs and fields cannot be blank or duplicated. Invalid cursor, future cursor, uncommitted step, malformed query, unsupported field, and unknown rule values return the established 400 envelope: {"error": "invalid_request", "message": "..."}. A valid unknown run is 404; corrupt catalogs, unsupported formats, and registered-file failures are 503 with the generic store-read envelope. Unexpected runtime failures remain 500.

Every step-scoped response includes the pinned through_cursor and exact step_n; cursors are never clamped. A response remains frozen after later commits when the same cursor is reused. Definitions and target declarations are available at zero commits, but no step response invents step 1. logged_empty is distinct from not_recorded, and both are distinct from a page filtered_empty. Rows are ordered by requested sort, simulator-declared tie-breaks, then _row_id, with bounded predicate-pushed pages rather than full evidence or decision materialization.

Evidence hits are triggered-subject observations only. Decision rows preserve decision_id, target_id, claimed contributing_rules provenance, payload_json, _row_id, observation metadata, and virtual commit identity. Neither hits nor decisions are evaluation truth. User Python owns rule execution, decision logic, evaluated populations, formulas, overlap arithmetic, and truth reconciliation.

Examples:

GET /api/v1/runs/01J.../rules
GET /api/v1/runs/01J.../rule-aggregates?through_cursor=12&step_n=5&rule_id=R12
GET /api/v1/runs/01J.../rule-aggregate-series?through_cursor=12&from_n=1&to_n=30&rule_id=R12&field=unique_triggered_n
GET /api/v1/runs/01J.../rules/R12/evidence?through_cursor=12&step_n=5&limit=100&sort=target_id:asc
GET /api/v1/runs/01J.../decision-status?through_cursor=12&step_n=5
GET /api/v1/runs/01J.../decisions/rows?through_cursor=12&step_n=5&filter=target_id:eq:%22A-19%22

Swagger documents these routes at /swagger/ and continues to serve Flask-RESTX assets locally; no CDN assets are used.

Lineage reads

These are read-only HTTP projections of ResultReader.list_lineage_stages and ResultReader.read_lineage_at_step. Flask does not declare stages, log observations, infer parents or statuses, execute a workflow, or derive counts. Missing is not zero. An unobserved stage is logged: false with status: null and empty counts. The Lineage UI is a later React task. The simulator continues to work without the monitor.

Routes

  • GET /api/v1/runs/{run_id}/lineage lists declared stages in declaration order. It has no accepted query parameters and is valid at zero commits. An old store, or a run with no declarations, returns "stages": [].
  • GET /api/v1/runs/{run_id}/lineage-observations requires through_cursor (nonnegative) and step_n (positive and committed at that cursor). There is no nearest-step, latest, series, trend, paging, filter, generation, or chart-range parameter. A frozen cursor that has not committed the requested step returns HTTP 400. Stage ids are never placed in URL paths.

Examples:

GET /api/v1/runs/01J.../lineage
GET /api/v1/runs/01J.../lineage-observations?through_cursor=12&step_n=5

Declarations envelope:

{
  "run_id": "01J...",
  "stages": [
    {
      "stage_id": "evaluate",
      "label": "Evaluate subjects",
      "description": "Apply the declared evaluation",
      "parents": ["prepare"],
      "counts": ["evaluated_n", "flagged_n"],
      "ordinal": 2
    }
  ]
}

Selected-step observations envelope:

{
  "run_id": "01J...",
  "through_cursor": 12,
  "step_n": 5,
  "as_of": "2025-01-06T00:00:00Z",
  "commit_id": 7,
  "observations": [
    {
      "stage_id": "evaluate",
      "logged": true,
      "status": "completed",
      "counts": {"evaluated_n": 8120, "flagged_n": 0}
    },
    {
      "stage_id": "publish",
      "logged": false,
      "status": null,
      "counts": {}
    }
  ]
}

Stored Lineage statuses are completed, skipped, and failed. Integers with magnitude >= 2^53 serialize as decimal strings.

Configuration

Key Required Meaning
RESULT_STORE Yes Filesystem path to the Mini Atlas result store. Never supplied by HTTP clients.

Release files for mini-atlas-monitor 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mini-atlas-monitor 0.2.0
File Size Uploaded
mini_atlas_monitor-0.2.0.tar.gz 716.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mini-atlas-monitor 0.2.0
File Interpreter ABI Platform
mini_atlas_monitor-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / mini_atlas_monitor-0.2.0.tar.gz

Download URL mini_atlas_monitor-0.2.0.tar.gz
Size 716.3 kB
Tags Source
SHA-256 checksum
How to use checksums
6ba25120314db8587c874b69fa9f650e7a2708c2365c8e1d0d39795a727ff61f
BLAKE2b-256 checksum
How to use checksums
858f55372dae53509d77fb6890f2b0970b0f5eef42d6a5064cb75a8fd0eb5f84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / mini_atlas_monitor-0.2.0-py3-none-any.whl

Download URL mini_atlas_monitor-0.2.0-py3-none-any.whl
Size 719.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f405c9a007c04bf5c90a9864469ea534166046f0569fc675bf7aee78c2438ae5
BLAKE2b-256 checksum
How to use checksums
5d85639280eab3bcb820d1a8fe18b5f2c45300075dc35b13392582b26d5737fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page