release: bump version to 0.53.0
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled

This commit is contained in:
rayd1o
2026-05-13 08:05:43 +08:00
parent b87cb310fd
commit d9efd98d26
56 changed files with 2318 additions and 243 deletions

View File

@@ -299,6 +299,17 @@ State semantics:
AISStream connectivity validation reads the saved collector configuration, environment variables, and `AISSTREAM_API_KEY` in `~/.zshrc` through `datasource_connectivity.py`. For actual collection, the most reliable path is saving the API key in `Settings -> Collector Settings -> AISStream Vessels`; if the key only lives in `~/.zshrc`, confirm that the backend process inherited it.
The console manages AISStream from `/datasources -> Realtime Streams`, not from the normal finite collection progress bar. The realtime stream API aggregates runtime state, health, configuration preview, and raw observation counters:
```http
GET /api/v1/realtime-sources
POST /api/v1/realtime-sources/{source}/start
POST /api/v1/realtime-sources/{source}/stop
POST /api/v1/realtime-sources/{source}/restart
```
`aisstream_vessels` and custom `source_type=websocket` sources appear in that API. They do not participate in one-click collection percentages; the UI interprets them as long-lived services with message counters, lag, last success, and last error.
### AIS Raw Observations And Aggregation
AIS observations do not directly replace final vessel records. They are first saved as raw observations:
@@ -318,7 +329,7 @@ GET /api/v1/visualization/vessels/{mmsi}/track
GET /api/v1/visualization/vessels/{mmsi}/conflicts
```
`/api/v1/vessels/snapshot` requires `bbox` and `zoom`, defaults to `limit=1000`, and caps `limit` at `5000`. It reads only aggregated `ais_raw_observations`; it no longer merges legacy `vessel_position` / `vessel_static` rows. The old `/api/v1/visualization/geo/vessels` endpoint has been removed and returns `410 Gone`.
`/api/v1/vessels/snapshot` requires `bbox` and `zoom`, defaults to `limit=1000`, and caps `limit` at `5000`. It prefers aggregated `ais_raw_observations`; when the current raw window is empty, it can fall back to the latest legacy `vessel_position` / `vessel_static` rows and marks that path with `diagnostics.legacy_fallback_used`. The old `/api/v1/visualization/geo/vessels` route has been removed.
Realtime deltas are sent through the `/ws` `vessels` channel. Clients must subscribe with the current viewport:

View File

@@ -288,7 +288,7 @@ Normalization:
Connectivity validation reads saved configuration, environment variables, and `AISSTREAM_API_KEY` from `~/.zshrc`. For actual collection, prefer saving the API key in collector settings. If the key only lives in `~/.zshrc`, confirm that the backend process inherited it; otherwise validation may pass while the collector runtime cannot read the key.
Connectivity validation and actual collection are separate actions. A banner such as `AISStream credentials configured, WebSocket endpoint format valid` only means the saved settings can be used for a connection attempt; runtime status may still be `disconnected`. Global AIS data is written locally only while the `aisstream_vessels` collector is `streaming` / `connected` and its message count plus `last_seen_at` keep advancing.
Connectivity validation and actual collection are separate actions. A banner such as `AISStream credentials configured, WebSocket endpoint format valid` only means the saved settings can be used for a connection attempt; runtime status may still be `disconnected`. Global AIS data is written locally only while `aisstream_vessels` is `streaming` / `connected` and its realtime stream counters plus `last_seen_at` keep advancing. Start, stop, reconnect, health, and counters are exposed through `/datasources -> Realtime Streams` and `/api/v1/realtime-sources`; AISStream is not counted in normal one-click collection progress.
The new vessel list entry point is no longer the legacy `/api/v1/visualization/geo/vessels` route. Earth initial state should call:
@@ -296,7 +296,7 @@ The new vessel list entry point is no longer the legacy `/api/v1/visualization/g
GET /api/v1/vessels/snapshot?bbox=lon_min,lat_min,lon_max,lat_max&zoom=12&limit=1000
```
That endpoint reads local aggregated `ais_raw_observations` only. Realtime updates use the `/ws` `vessels` channel; subscriptions must include `bbox`, `zoom`, and `limit`. The server filters updates per connection and merges collector broadcasts every second, keeping only the latest position per MMSI.
That endpoint prefers local aggregated `ais_raw_observations`; when the current raw window is empty, it can fall back to the latest legacy `vessel_position` / `vessel_static` rows and exposes that through `diagnostics.legacy_fallback_used`. Realtime updates use the `/ws` `vessels` channel; subscriptions must include `bbox`, `zoom`, and `limit`. The server filters updates per connection and merges collector broadcasts every second, keeping only the latest position per MMSI.
## Custom REST / WebSocket Mapping Runtime

View File

@@ -154,7 +154,7 @@ The `earth:compute-center-location-saved` reconciliation pipeline is deliberatel
The vessel layer now uses `/api/v1/vessels/snapshot` for the initial viewport snapshot and the `/ws` `vessels` channel for realtime deltas. Snapshot requests must include `bbox`, `zoom`, and a bounded `limit`; the backend defaults to `limit=1000` and caps it at `5000`. WebSocket subscriptions must include the same viewport fields so the server can filter updates per connection.
The legacy `/api/v1/visualization/geo/vessels` endpoint has been removed and returns `410 Gone`. Frontend code should fetch a snapshot for the current viewport when the layer opens, then subscribe to `vessels` deltas. After map pan or zoom, reload the snapshot and send a fresh vessels subscription. The backend no longer merges legacy `vessel_position` / `vessel_static` rows into vessel snapshots, so the frontend must not depend on old BarentsWatch-only fallback rows.
The legacy `/api/v1/visualization/geo/vessels` route has been removed. Frontend code should fetch a snapshot for the current viewport when the layer opens, then subscribe to `vessels` deltas. After map pan or zoom, reload the snapshot and send a fresh vessels subscription. The backend only falls back to legacy `vessel_position` / `vessel_static` rows when the current raw window is empty; frontend code can detect that state through `diagnostics.legacy_fallback_used`.
The new layer API family is `/api/v1/layers/*`, which separates map rendering payloads from aggregate panel statistics. Layer requests must include `bbox`, `zoom`, and a bounded `limit`; responses include `visible_count`, `returned_count`, and `diagnostics`, where `degraded`, `truncated`, and `limit_clamped` are the frontend signals for fallback UI. Right-side aggregate panels should not sum the layer response. They should read `/api/v1/data-products` or `/api/v1/data-products/{product_id}/status`, because those statistics stay global and do not change with the viewport.

View File

@@ -130,11 +130,12 @@ Steps:
3. Keep the default endpoint `wss://stream.aisstream.io/v0/stream`
4. Click the plug icon to test; confirm it reports `Reachable`
5. Save collector settings
6. Trigger the `aisstream_vessels` collector from the collection scheduler
7. Watch the `AISStream Runtime` panel:
6. Open the `Realtime Streams` tab on `/datasources` and find `AISStream Realtime Vessels`
7. Use `Start`, `Stop`, or `Reconnect` there. The normal `Collection Tasks` tab does not count AISStream in one-click collection or percentage progress
8. Watch the realtime stream panel:
- `streaming` / `connected` means the live stream is being consumed
- `messages this round` should keep growing
- `disconnected` with `ConnectionResetError` means the upstream or network dropped; re-trigger or wait for reconnect
- `total stored`, `last 24h`, `last 1h`, and `unique MMSI` show historical collection volume
- `disconnected` with a recent error means the upstream or network dropped; click `Reconnect`
## Configure AI Credentials
@@ -203,7 +204,7 @@ To let a regular user read developer or operations docs, add `docs_developer` or
## Data Exploration
- `/datasources`: source directory. It can be filtered by product domain, layer/module, enabled state, last run status, whether collected records exist, and search text. Selecting rows triggers only those sources; with no selected rows, `Collect current filter` triggers the filtered scope. Clicking a name opens an info drawer showing endpoint, headers, base config, and built-in flag; endpoint/credentials editing happens at `/settings -> Collector Settings`. The `Collecting N` tag under the overall progress can be clicked to expand the current collection task list
- `/datasources`: source directory. The `Collection Tasks` tab is for one-shot, scheduled, and finite collectors; it can be filtered by product domain, layer/module, enabled state, last run status, whether collected records exist, and search text. Selecting rows triggers only those sources; with no selected rows, `Collect current filter` triggers the filtered scope. The `Realtime Streams` tab is for AISStream / WebSocket long connections and shows connection health, stored totals, time-window counters, and Start / Stop / Reconnect actions. Clicking a name opens an info drawer showing endpoint, headers, base config, and built-in flag; endpoint/credentials editing happens at `/settings -> Collector Settings`. The `Collecting N` tag under the overall progress can be clicked to expand the current collection task list
- `/data`: collected data table — used to verify "did data arrive", "is the freshness right", "does a source emit valid records"
- `/bgp`: BGP detail page with list + detail + analysis; complements the BGP layer on Earth
- `/alerts/system`, `/alerts/bgp`, `/alerts/situational`: system, BGP, and situational alerts

View File

@@ -22,10 +22,10 @@ image_exists AND stamp_non_empty AND fingerprint_match
### Fix
The stamp file moved to a persistent cache path:
The stamp file moved from a temporary location to a persistent cache path:
```bash
AI_PROVIDER_BUILD_STAMP_FILE="$HOME/.cache/planet/aiprovider_build.sha256"
AI_PROVIDER_BUILD_STAMP_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/planet/aiprovider_build.sha256"
```
Writing the stamp creates the directory first:
@@ -92,7 +92,7 @@ COPY aiprovider /app/aiprovider
### Runtime Configuration
Before starting AI Provider, `planet.sh` generates a temporary env-file and passes it to Compose or the manual `docker run` fallback. Configuration priority:
Before starting AI Provider, `planet.sh` generates a current-user runtime env-file and passes it to Compose or the manual `docker run` fallback. The default path is `${XDG_STATE_HOME:-$HOME/.local/state}/planet/aiprovider_runtime.env`. Configuration priority:
1. `aiprovider/.env`
2. simple `export AI_...=...` or `AI_...=...` lines from `~/.zshrc`
@@ -188,6 +188,62 @@ Before the stamp path fix:
After moving the stamp file, plain `restart` uses the same `stop + start` behavior and the same fingerprint check as `restart -b`.
## State Files, Logs, and Failed-Start Cleanup
`planet.sh` no longer writes PID files, logs, or runtime env-files to fixed `/tmp/planet_*` paths. The default state directory is:
```bash
${XDG_STATE_HOME:-$HOME/.local/state}/planet
```
At startup the script creates this directory and tries to set it to `700`. The current files include:
- `backend.pid` / `frontend.pid` / `motion_agent.pid`
- `backend.log` / `frontend.log` / `motion_agent.log`
- `aiprovider_build.log`
- `aiprovider_runtime.env`
- `ports.env`
PID writes validate that the PID is a positive integer, include a trailing newline, and try to set file mode `600`. PID reads ignore invalid content instead of passing it to `kill`.
After a successful `start`, the script records the ports in `ports.env`. Later `./planet.sh health` calls prefer the last started ports; if the state file is missing, health checks fall back to the defaults `8000`, `3000`, `8010`, and `8765`. This avoids checking default ports after starting with custom ports.
Startup now has light failed-start cleanup. If `start` exits before completing, the script only cleans local processes that this run already started: backend, frontend, and Motion Agent. It does not stop services after a successful start. AI Provider, PostgreSQL, and Redis keep their existing container lifecycle behavior.
## Health Checks and Hardening
HTTP readiness checks now use `curl -fsS --max-time`, so 4xx and 5xx responses are no longer treated as healthy.
Process termination now validates:
- signal names are limited to `TERM`, `KILL`, `INT`, and `HUP`;
- PIDs must be positive integers;
- process group IDs must be positive integers.
This prevents bad PID files or invalid signals from reaching `kill`.
Frontend and Motion Agent startup failures now call `print_port_listener_details()`, matching backend port diagnostics. The Windows-side listener and cleanup path still only runs when WSL is detected.
## Cross-Platform Notes
The script is currently Linux-first with WSL enhancements. Normal Linux runs do not execute the PowerShell path; WSL gets extra Windows listener, portproxy, and camera guidance.
To make this single script fully portable across Linux, macOS, and WSL, the remaining platform differences should be wrapped behind compatibility helpers:
- `stat --format`, `sort -V`, and `xargs -r` are GNU-style and are not fully compatible with default macOS BSD tools.
- `hostname -I`, `ss`, `fuser`, and `systemctl` are usually unavailable on macOS.
- `tac` may be missing on macOS; use `awk` or Python as a fallback.
- Docker Desktop on macOS does not use `systemctl` daemon diagnostics.
- Camera auto-detection relies on `/dev/video*` / `v4l2-ctl`, which is Linux-specific; macOS should use explicit camera URLs or a separate AVFoundation detector.
The recommended direction is a small platform compatibility layer for port listener detection, version comparison, file metadata, reverse tail, LAN IP discovery, and Docker daemon diagnostics, instead of scattering more platform branches throughout service startup logic.
## Production Delivery Boundary
`planet.sh` is a local development convenience script, not the production startup entrypoint. Production delivery should use Kubernetes `Deployment`, `Service`, `Ingress`, and readiness/liveness probes for ports, health checks, restarts, and rolling upgrades. This removes the need for a host script to reclaim local ports and avoids running the Vite dev server in production.
The production frontend shape is `vite build` static output served by nginx/Caddy or an equivalent HTTP server. Do not use `bun run dev` or `vite preview` in production. The project does not maintain a parallel Webpack build chain; if a future enterprise requirement needs closer Webpack-ecosystem compatibility, run an Rsbuild/Rspack spike first. Electron should only be evaluated when the official target becomes an offline desktop application.
## Optional Motion Agent Startup
`planet.sh` can now manage the local Motion Capture Agent. It is disabled by default so ordinary development machines do not fail startup when cameras, OpenCV, or MediaPipe are unavailable.

View File

@@ -34,7 +34,7 @@ After landing on the `/admin` dashboard, here's a recommended walk-through:
1. `/settings?tab=collector_credentials`: pick a collector and click the plug icon to test connectivity. Free collectors (e.g. open BGP) usually work right away; credential-bearing ones like `AISStream` or `BarentsWatch` need an API key / client secret first
2. `/ai?tab=providers`: fill an LLM provider (e.g. `minimax` / `openai`), model, base URL, API key, and click the plug at the end of the base URL to test. WebSearch / OCR tools are optional
3. `/datasources` or `/data`: check whether the collectors have produced data
3. `/datasources` or `/data`: check whether collectors have produced data. Use `/datasources -> Collection Tasks` for finite collectors, and `/datasources -> Realtime Streams` for AISStream / WebSocket health and counters
4. `/alerts/system`: verify system alerts look right
5. `/users` (super_admin only): open accounts for teammates or adjust their groups