14 KiB
Android Cast — exposed services catalog
Validated: 2026-06-10 after FE apps.conf consolidation + BE sync. Public base: https://apps.f0xx.org.
Documentation index: README.md · Companion: INFRA.md, 20260608_BE_SERVICES_and_infra.md
Table of contents
- Validation snapshot
- Hub landing
- Console home
- Issues (crash reports)
- Tickets
- Graphs
- Remote access
- RBAC / access control
- APK builder
- Git (Gitea)
- OTA updates
- Heartbeat (device)
- Auth & account security
- URL shortener (preview — not deployed)
- Non-HTTP services
- Validation scripts
Documentation index: README.md
Validation snapshot
Run: examples/crash_reporter/backend/scripts/validate_be_services.sh
| Check | URL / target | 2026-06-10 |
|---|---|---|
| Hub | /app/androidcast_project/ |
✅ HTTP 200 |
| Crashes console | …/crashes/ |
✅ HTTP 302 → login |
| Graphs | …/graphs/ |
✅ HTTP 302 → login |
| Builder | …/build/ |
✅ HTTP 302 → login |
| Git | …/git/ |
✅ HTTP 200 |
| OTA channel | /v0/ota/channel/stable.json |
⚠️ HTTP 404 (FE proxy OK; artifact or BE location missing) |
| Crash upload | …/crashes/api/upload.php GET |
✅ HTTP 400 (expects POST JSON) |
| Heartbeat | …/crashes/api/heartbeat.php GET |
✅ HTTP 405 (expects POST) |
| Graph upload | …/graphs/api/graph_upload.php GET |
✅ HTTP 400 (expects POST) |
| Two-factor | …/crashes/two-factor |
✅ HTTP 302 → login (no pending session) |
Alerts — may need follow-up patch
- OTA: Public returns 404; BE direct
curl -H 'Host: apps.f0xx.org' http://artc0…/v0/ota/channel/stable.jsonreturned HTML lander redirect (not JSON). Confirm BElisten 80haslocation ^~ /v0/ota/before catch-all, and publishstable.jsonunderota-artifacts/v0/ota/channel/. - 2FA: Fixed in repo —
completeTotpLogin()no longer clears pending session on wrong code; login redirects to/two-factorwhen pending. Sync BE (Auth.php,index.php,two_factor_challenge.php,app.css).
Hub landing
Web: https://apps.f0xx.org/app/androidcast_project/
Marketing multipage shell; left nav links to Console, Git, Issues, Tickets, Graphs, Remote access, Builder. Shared session cookie ac_crash_sess path /app/androidcast_project.
| Kind | Path | Notes |
|---|---|---|
| Static/PHP | index.php |
Hub landing |
| CSS/JS | hub.css, hub-landing.css, assets/hub-*.js |
Theme + i18n |
| Crashes assets | …/crashes/assets/css/app.css |
Shared console theme |
No device ingest on hub root.
Console home
Web: https://apps.f0xx.org/app/androidcast_project/crashes/?view=home (auth required)
Landing cards: Issues, New issue, Tickets, New ticket, Graphs; quick links to all services.
Issues (crash reports)
Web: https://apps.f0xx.org/app/androidcast_project/crashes/?view=reports
Triage anonymous crash JSON; grouped/by-time views; tag editor; tree expand.
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
POST |
…/crashes/api/upload.php |
None | Device crash ingest (JSON or gzip JSON) |
GET |
…/crashes/api/reports.php |
Session | List/filter reports (console JS) |
POST |
…/crashes/api/report_tags.php |
Session | Update report tags |
POST |
…/crashes/api/report_viewed.php |
Session | Mark report viewed |
GET |
…/crashes/api/tag_catalog.php |
Session | Tag suggestions |
GET |
…/crashes/api/diag.php |
Optional | Diagnostics (may 403 at edge) |
Upload via curl
BASE=https://apps.f0xx.org/app/androidcast_project/crashes
SAMPLE=examples/crash_reporter/sample_crash_java.json
RID="manual-$(date +%s)"
jq --arg rid "$RID" '.report_id = $rid' "$SAMPLE" | \
curl -sS -X POST "$BASE/api/upload.php" \
-H 'Content-Type: application/json' --data-binary @-
Gzip upload smoke: examples/crash_reporter/backend/scripts/test_gzip_upload.sh
Bulk / synthetic issues
- Optional payload fields:
ingest.source,ingest.client_id,ingest.run_id— see OPEN_API.md. - Loop
upload.phpwith variedreport_id/ fingerprints for load tests. - Tag harness traffic
syntheticvia console orreport_tags.php.
Tickets
Web: https://apps.f0xx.org/app/androidcast_project/crashes/?view=tickets
Roadmap / QA tasks; workflow tags (ticket vs issue meta).
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
GET |
…/crashes/api/tickets.php |
Session | List tickets |
POST |
…/crashes/api/ticket_create.php |
Session | Create ticket/issue |
POST |
…/crashes/api/ticket_update.php |
Session | Update fields/tags |
POST |
…/crashes/api/ticket_tags.php |
Session | Tag catalog ops |
POST |
…/crashes/api/ticket_comments.php |
Session | Comments |
POST |
…/crashes/api/ticket_upload.php |
Session | Attachment upload |
GET |
…/crashes/api/ticket_attachments.php |
Session | List attachments |
GET |
…/crashes/api/ticket_attachment.php |
Session | Download attachment |
Create via UI
- Issues view: New issue →
ticket_create.js→ticket_create.phpwithissuemeta tag. - Tickets view / home: New ticket → same API with
ticketmeta tag.
Create via curl (session cookie)
BASE=https://apps.f0xx.org/app/androidcast_project/crashes
JAR=/tmp/ac-cookie.txt
curl -sS -c "$JAR" -b "$JAR" -X POST -d 'username=admin&password=admin' "$BASE/login" -o /dev/null
curl -sS -b "$JAR" -X POST -H 'Content-Type: application/json' \
-d '{"title":"API test","brief":"from curl","body":"","tags":[{"id":"ticket","label":"ticket","bg":"#6366f1"},{"id":"open","label":"open","bg":"#22c55e"}]}' \
"$BASE/api/ticket_create.php"
Graphs
Web: https://apps.f0xx.org/app/androidcast_project/graphs/
Session metrics dashboards (user / slug / platform scopes); drag-reorder bricks; empty-session notice when no graph_upload data.
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
GET |
…/graphs/api/graphs.php?days=14 |
Session | Aggregated metrics JSON |
POST |
…/graphs/api/graph_upload.php |
Device/session | Ingest graph_session NDJSON/JSON |
Graphs PHP routes through crashes public/index.php (?view=graphs).
Fake session data (dev / BE)
# Generate NDJSON
php examples/crash_reporter/backend/scripts/generate_fake_graph_sessions.php \
--devices=100 --per-device=6 --out=/tmp/sessions.ndjson
# SQL import on BE (when HTTP upload times out)
php examples/crash_reporter/backend/scripts/ndjson_to_graph_sql.php /tmp/sessions.ndjson | \
ssh alpine-be 'mariadb androidcast_crashes'
API smoke: examples/crash_reporter/backend/scripts/test_graphs_api.sh
Remote access
Web: https://apps.f0xx.org/app/androidcast_project/crashes/?view=remote_access (RBAC: remote_access_view)
Operator console: whitelist devices, open WireGuard or RSSH sessions.
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
POST |
…/crashes/api/remote_access.php?action=… |
Session | whitelist, open_session, dashboard, … |
POST |
…/crashes/api/heartbeat.php |
None | Device RA poll (heartbeat.type=ra) |
Device flow: app polls heartbeat.php → operator uses console → next poll returns connect payload.
Smoke: CRASHES_BASE=https://apps.f0xx.org/app/androidcast_project/crashes examples/crash_reporter/backend/scripts/test_remote_access_api.sh
Prod checklist: examples/crash_reporter/backend/scripts/verify_remote_access_prod.sh
RBAC / access control
Web: https://apps.f0xx.org/app/androidcast_project/crashes/?view=rbac (admin)
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
GET/POST |
…/crashes/api/rbac.php |
Session | Roles, memberships, lockouts |
GET/POST |
…/crashes/api/users.php |
Session | User admin |
Smoke: examples/crash_reporter/backend/scripts/test_rbac_api.sh
APK builder
Web: https://apps.f0xx.org/app/androidcast_project/build/
Docker CI: trigger builds, stream logs, OTA artifact option.
Related endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
GET |
…/build/api/health.php |
Session | Docker/socket health |
GET |
…/build/api/builds.php |
Session | Build history |
POST |
…/build/api/build_trigger.php |
Session | Start build |
GET |
…/build/api/build_log.php?id= |
Session | Log tail |
POST |
…/build/api/build_actions.php |
Session | Cancel / rerun |
Shared login with crashes (ac_crash_sess). See BUILD_DEPLOY.md.
Git (Gitea)
Web: https://apps.f0xx.org/app/androidcast_project/git/
FE proxies to http://artc0.intra.raptor.org:3000/ (Gitea). Canonical git remote: git://f0xx.org/android_cast.
No Android Cast PHP on this path.
OTA updates
Web channel: https://apps.f0xx.org/v0/ota/channel/stable.json
Device setting: ota.base_url in examples/settings.json → https://apps.f0xx.org/v0/ota/channel/stable.json.
Layout
See OTA.md: v0/ota/channel/{stable,staging,…}.json → manifest → .otapkg / .otabundle.zip.
Publish (operator)
./scripts/generate-ota-v0.sh app/build/outputs/apk/release/app-release.apk \
https://apps.f0xx.org ./out/ota staging
OTA_DEPLOY_TARGET=… ./scripts/deploy-ota-staging.sh
BE mount: …/androidcast_project/ota-artifacts/v0/ — prepare-be-ota-mount.sh.
Status 2026-06-10: FE /v0/ota/ → BE :80 configured; channel file not yet served (404 / lander) — publish artifacts + verify BE nginx location ^~ /v0/ota/.
Heartbeat (device)
Web: none (app service only)
Endpoint: POST https://apps.f0xx.org/app/androidcast_project/crashes/api/heartbeat.php
JSON body with heartbeat object: session stats, remote-access poll (type: ra), etc.
curl -sS -X POST -H 'Content-Type: application/json' \
-d '{"heartbeat":{"type":"ping","device_id":"test-device"}}' \
https://apps.f0xx.org/app/androidcast_project/crashes/api/heartbeat.php
Auth & account security
| Page | URL |
|---|---|
| Login | …/crashes/login |
| Register | …/crashes/register |
| Two-factor challenge | …/crashes/two-factor |
| Account security (TOTP enroll) | …/crashes/account-security |
| Email verify | …/crashes/verify-email?token= |
| Method | Endpoint | Purpose |
|---|---|---|
POST |
…/crashes/api/auth_register.php |
Registration API |
TOTP verify script: examples/crash_reporter/backend/scripts/verify_auth_totp.php
Flow doc: 20260607-2FA-email-mobile-auth-flow.md
URL shortener (preview — not deployed)
Web: https://s.f0xx.org (dedicated vhost; FE TLS live)
| Kind | Path | Notes |
|---|---|---|
| Health | GET /api/v1/health |
Stub until PHP handlers deployed |
| Shorten | POST /api/v1/shorten |
Bearer token; see SPEC |
| QR | GET /api/v1/qr/{slug}.png |
PNG |
| Redirect | GET /{slug} |
302 → original URL |
Spec: specs/20100611_3_url_shortener.md · scaffold: backend/url-shortener/
export BASE=https://s.f0xx.org
curl -sS "$BASE/api/v1/health"
# Full cookbook: backend/url-shortener/scripts/demo_curl.sh (needs BEARER when live)
Non-HTTP services
| Service | Access | Used by |
|---|---|---|
| WireGuard | ra.apps.f0xx.org:45340/udp |
Remote access lab mode |
| RSSH bastion | ra.apps.f0xx.org:443/tcp |
Reverse SSH alpha mode |
| Cast LAN | UDP/TCP :41235, discovery :41234 |
Screen mirror (no BE) |
| MQTT OTA (optional) | mqtt://host:port/v0/ota/… |
Retained topic payloads |
Validation scripts
| Script | Purpose |
|---|---|
validate_be_services.sh |
Public HTTP smoke (this doc’s snapshot) |
test_gzip_upload.sh |
Crash upload plain + gzip |
test_graphs_api.sh |
Graphs JSON API |
test_remote_access_api.sh |
RA whitelist + session |
test_rbac_api.sh |
RBAC API |
test_rssh_api.sh |
RSSH mode API |
test_tags_api.sh |
Report tag API |
verify_remote_access_prod.sh |
Prod RA checklist |
FE nginx template: examples/crash_reporter/backend/nginx/fe/apps.conf
Regenerate FE patch: scripts/generate-fe-nginx-patch.sh