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
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**English** | [Українська](README.uk.md)

Current Client version: **1.0.0**.
Current Client version: **1.1.0**.

> Dataset Server v1 is the source of truth for published metadata and binaries.
> See the generated [public catalog](CATALOG.md).
Expand All @@ -15,6 +15,8 @@ dsm-client sync
dsm-client sync --check
dsm-client fetch iv.dev.4.ff.1 --format rosbag
dsm-client fetch iv.dev.4.ff.1 --format rosbag2
dsm-client prepare-run iv.dev.4.ff.1 \
--implementation vins-neo --suite smoke --format rosbag2
dsm-client validate
```

Expand All @@ -41,6 +43,23 @@ without persisting the token. Run `import-catalog` after publication.
The former scripts and `IVINS_*` environment variables remain compatibility
interfaces through Client 1.x. `DSM_*` always takes precedence.

## Runtime profiles and dataset runs

`prepare-run` derives the hardware profile from the immutable Dataset Server
manifest. `--profile` is only an assertion and fails on disagreement. The first
validated runtime profile is `dev_04`; `dev_4` remains an alias. Other profiles
fail explicitly with `runtime profile unavailable` until their sensor/config
contracts are validated.

The command authenticates only with `DSM_SERVER_TOKEN`, refuses to send that
token over plain HTTP except to a loopback test-server, verifies every cached
artifact by SHA-256, and emits stable JSON containing the dataset/profile,
artifact version/SHA/path, VINS config SHA, topics, launch arguments and smoke
acceptance settings. A published ROS1 bag is converted with pinned
`rosbags==0.11.3`; source and converted SHA-256 values remain separate. Tiny or
invalid bag fixtures cannot qualify a real run. See the
[runtime run contract](docs/runtime-runs.md).

This repository is a client catalog for evaluating multiple visual-inertial navigation
systems (VINS) against public and iVINS MAV recordings. Dataset recordings are
**not stored in this repository**. Manifests point to authoritative download
Expand Down
20 changes: 19 additions & 1 deletion README.uk.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,36 @@

[English](README.md) | **Українська**

Поточна версія Client: **1.0.0**. Канонічний CLI — `dsm-client`; сервер є
Поточна версія Client: **1.1.0**. Канонічний CLI — `dsm-client`; сервер є
єдиним джерелом опублікованого стану, а цей репозиторій містить manifests,
configs і детермінований generated catalog.

```powershell
python -m pip install -e .
dsm-client sync
dsm-client fetch iv.dev.4.ff.1 --format rosbag
dsm-client prepare-run iv.dev.4.ff.1 `
--implementation vins-neo --suite smoke --format rosbag2
dsm-client publish ID --format rosbag --version 1 --path FILE --metadata META.json
dsm-client validate
```

## Runtime-профілі та dataset runs

`prepare-run` визначає hardware-профіль з immutable manifest Dataset Server.
Параметр `--profile` є лише assertion і завершується помилкою при розбіжності.
Перший валідований runtime-профіль — `dev_04`; `dev_4` залишається alias. Для
інших профілів повертається явне `runtime profile unavailable`, доки їхні
sensor/config contracts не пройдуть валідацію.

Команда бере ключ лише з `DSM_SERVER_TOKEN`, відмовляється передавати його через
HTTP (крім loopback test-server), перевіряє SHA-256 при кожному використанні
кешу й повертає стабільний JSON із dataset/profile, artifact version/SHA/path,
SHA конфігурації VINS, topics, launch arguments і smoke acceptance settings.
ROS1 bag конвертується зафіксованим `rosbags==0.11.3`; SHA source і converted
artifact зберігаються окремо. Малі або невалідні fixtures не можуть пройти
реальний gate. Див. [контракт runtime run](docs/runtime-runs.uk.md).

Канонічні змінні: `DSM_SERVER_URL`, `DSM_SERVER_TOKEN`, `DSM_RAW_ROOT`.
Старі `IVINS_*` приймаються до Client 2.0 з попередженням; `DSM_*` має вищий
пріоритет.
Expand Down
7 changes: 3 additions & 4 deletions configurations/ivins/VINS-NEO/dev_04/ivins_dev04_config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
%YAML:1.0

# VINS-NEO configuration candidate for iVINS dev_04.
# The current values preserve the shared VINS-Mono-style baseline.
# TODO: verify this schema and required keys against the exact pinned VINS-NEO
# revision before using it; no implementation-specific values are assumed here.
# Validated VINS-NEO runtime configuration for iVINS dev_04.
# Runtime identity, compatible datasets and launch settings are versioned in
# runtime-profiles/dev_04.yaml.

#common parameters
imu_topic: "/imu0"
Expand Down
4 changes: 3 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ flowchart TB
CLI["dsm-client CLI"] --> Validate["Catalog and profile validator"]
CLI --> Sync["Deterministic catalog importer"]
CLI --> Raw["Fetch, conversion and publish workflows"]
CLI --> Prepare["Runtime profile and prepare-run"]
Manifests["Dataset and configuration manifests"] --> Validate
Aliases["Profile alias manifest"] --> Validate
Families["Family profile manifest"] --> Validate
Sync --> Generated["Bilingual generated catalog"]
Raw --> Artifacts["Ignored local artifact hierarchy"]
Prepare --> Artifacts
```

## Catalog and artifact data flow
Expand Down Expand Up @@ -52,7 +54,7 @@ flowchart LR
Python --> CLI["Installed dsm-client"]
CLI --> Checkout["Versioned manifests and configs"]
CLI --> Local["datasets/*/artifacts ignored by Git"]
CLI -->|"HTTP /v1 with memory-only token"| Server["Server runtime"]
CLI -->|"HTTPS /v1 with environment-only token"| Server["Server runtime"]
```

## Repository interactions
Expand Down
4 changes: 3 additions & 1 deletion docs/architecture.uk.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ flowchart TB
CLI["CLI dsm-client"] --> Validate["Validator catalog і profiles"]
CLI --> Sync["Детермінований catalog importer"]
CLI --> Raw["Fetch, conversion і publish workflows"]
CLI --> Prepare["Runtime profile і prepare-run"]
Manifests["Маніфести datasets і configurations"] --> Validate
Aliases["Маніфест profile aliases"] --> Validate
Families["Маніфест family profiles"] --> Validate
Sync --> Generated["Двомовний generated catalog"]
Raw --> Artifacts["Ігнорована локальна hierarchy artifacts"]
Prepare --> Artifacts
```

## Потік catalog і artifact data
Expand Down Expand Up @@ -52,7 +54,7 @@ flowchart LR
Python --> CLI["Встановлений dsm-client"]
CLI --> Checkout["Версіоновані manifests і configs"]
CLI --> Local["datasets/*/artifacts, ігноровані Git"]
CLI -->|"HTTP /v1 з memory-only token"| Server["Runtime сервера"]
CLI -->|"HTTPS /v1 з environment-only token"| Server["Runtime сервера"]
```

## Взаємодія репозиторіїв
Expand Down
36 changes: 36 additions & 0 deletions docs/runtime-runs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Runtime profiles and prepared dataset runs

[Українська версія](runtime-runs.uk.md)

DataSetsManager Client owns the versioned hardware-profile, implementation
configuration and dataset-suite contract. VINS-NEO owns launch and runtime
behavior. The Dataset Server remains the source of immutable artifact version,
size and SHA-256.

## Prepare `iv.dev.4.ff.1`

```bash
export DSM_SERVER_URL=https://datasetsmanager.drone-age.org
export DSM_SERVER_TOKEN='value-from-an-approved-secret-store'
dsm-client prepare-run iv.dev.4.ff.1 \
--implementation vins-neo \
--suite smoke \
--format rosbag2 > run-manifest.json
```

The profile comes from the server dataset manifest. An optional `--profile`
does not override it. The command fails on a missing profile/config, suite
mismatch, unsafe path, authentication error, checksum mismatch, invalid bag or
non-loopback HTTP credential transport.

Artifact paths are content-addressed. Cache reuse recalculates SHA-256 before
returning a run manifest. ROS1 conversion is pinned to `rosbags==0.11.3`; the
manifest records both source and converted digests. The test-only
`--allow-test-fixture` switch exists for the local Server contract test and must
never be passed by a VINS runner or release job.

For a tokenless Raspberry Pi run, prepare and verify the artifact plus manifest
on a trusted host through HTTPS, transfer the artifact, config and manifest as
one integrity-checked bundle, and run the VINS gate without exporting the DSM
token on the Pi. AMD64 evidence is development-only; release evidence requires
the native Debian 13 ARM64 rerun.
36 changes: 36 additions & 0 deletions docs/runtime-runs.uk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Runtime-профілі та підготовлені dataset runs

[English version](runtime-runs.md)

DataSetsManager Client володіє версіонованим контрактом hardware-профілю,
конфігурації реалізації та dataset suite. VINS-NEO володіє launch/runtime
поведінкою. Dataset Server залишається джерелом immutable version, size і
SHA-256 артефакту.

## Підготовка `iv.dev.4.ff.1`

```bash
export DSM_SERVER_URL=https://datasetsmanager.drone-age.org
export DSM_SERVER_TOKEN='значення-з-погодженого-сховища-секретів'
dsm-client prepare-run iv.dev.4.ff.1 \
--implementation vins-neo \
--suite smoke \
--format rosbag2 > run-manifest.json
```

Профіль береться з server dataset manifest. Необов'язковий `--profile` не
перевизначає його. Команда повертає FAIL за відсутнього профілю/config, suite
mismatch, небезпечного шляху, помилки автентифікації, checksum mismatch,
невалідного bag або спроби передати credential через не-loopback HTTP.

Шляхи артефактів content-addressed. Перед повторним використанням кешу SHA-256
обчислюється заново. Конвертація ROS1 зафіксована на `rosbags==0.11.3`; manifest
містить окремі source і converted digests. Test-only параметр
`--allow-test-fixture` існує лише для локального Server contract test і не може
використовуватись VINS runner або release job.

Для Raspberry Pi без токена підготуйте й перевірте artifact та manifest на
довіреному host через HTTPS, передайте artifact, config і manifest одним
пакетом із integrity check та запустіть VINS gate без `DSM_SERVER_TOKEN` на Pi.
AMD64 evidence є development-only; release evidence потребує повторного
нативного запуску на Debian 13 ARM64.
2 changes: 1 addition & 1 deletion dsm_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""DataSetsManager Client 1.x."""

__version__ = "1.0.0"
__version__ = "1.1.0"
46 changes: 46 additions & 0 deletions dsm_client/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
from __future__ import annotations

import argparse
import json
import os
from pathlib import Path
import sys
from collections.abc import Callable

from scripts import catalog_admin, raw_catalog, validate_catalog
from .runtime import PrepareRunError, prepare_run, stable_json


def invoke(main: Callable[[], int], program: str, arguments: list[str]) -> int:
Expand All @@ -25,13 +29,55 @@ def main() -> int:
commands.add_parser("sync", help="import the canonical server catalog")
for name in ("fetch", "publish", "raw"):
commands.add_parser(name)
prepare = commands.add_parser(
"prepare-run", help="prepare an immutable dataset/runtime run manifest"
)
prepare.add_argument("dataset_id")
prepare.add_argument("--implementation", required=True)
prepare.add_argument("--suite", required=True)
prepare.add_argument("--format", choices=("rosbag", "rosbag2"), required=True)
prepare.add_argument("--profile", help="assert the profile derived from the dataset manifest")
prepare.add_argument(
"--server-url", "--dsm-server-url", dest="server_url",
default=os.environ.get("DSM_SERVER_URL"),
)
prepare.add_argument(
"--cache-dir",
default=os.environ.get("DSM_CACHE_DIR", str(Path.home() / ".cache" / "datasetsmanager")),
)
prepare.add_argument("--allow-test-fixture", action="store_true", help=argparse.SUPPRESS)
args, forwarded = parser.parse_known_args()
if args.command == "validate":
if forwarded:
parser.error(f"unrecognized arguments: {' '.join(forwarded)}")
return validate_catalog.main()
if args.command == "sync":
return invoke(catalog_admin.main, "dsm-client sync", ["import-catalog", *forwarded])
if args.command == "prepare-run":
if forwarded:
parser.error(f"unrecognized arguments: {' '.join(forwarded)}")
if not args.server_url:
parser.error("--server-url or DSM_SERVER_URL is required")
try:
value = prepare_run(
dataset_id=args.dataset_id,
implementation=args.implementation,
suite_name=args.suite,
requested_format=args.format,
server_url=args.server_url,
token=os.environ.get("DSM_SERVER_TOKEN", ""),
cache_dir=Path(args.cache_dir).expanduser(),
asserted_profile=args.profile,
allow_test_fixture=args.allow_test_fixture,
)
sys.stdout.write(stable_json(value))
return 0
except PrepareRunError as exc:
print(
json.dumps({"status": "error", "message": str(exc)}, sort_keys=True),
file=sys.stderr,
)
return 2
if args.command == "raw":
return invoke(raw_catalog.main, "dsm-client raw", forwarded)
return invoke(raw_catalog.main, f"dsm-client {args.command}", [args.command, *forwarded])
Expand Down
Loading