corev0.02Use role tags to filter content.
[MOBILE] KMM Android/iOS app dev[FE] Web frontend (React/Tailwind) dev[BE-RUST] Axum service dev[BE-DB] PostgreSQL/Redis ops[BE-RUST][FE][MOBILE]| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /api/ |
API metadata/version | none |
| GET | /robots.txt |
SEO robots | none |
| GET | /sitemap.xml |
SEO sitemap | none |
| GET | /healthz |
Liveness/readiness | none |
| GET | /nonce |
CSRF nonce for next POST (JSON) | none |
/api/ response
{ "name":"server_generic", "version":"0.02", "time":"ISO-8601", "status":"ok" }
/nonce response
{ "nonce":"base64url-32", "expires_in_sec":300 }
[MOBILE][FE][BE-RUST]All errors map to:
{ "error": { "code":"STRING", "http":INT, "message":"STRING", "trace_id":"UUIDv4" } }
401: UNAUTHENTICATED403: FORBIDDEN404: NOT_FOUND409: CONFLICT422: INVALID_INPUT429: RATE_LIMITED (Retry-After header present)5xx: SERVER_ERROR[BE-RUST][BE-DB][FE]| Key | Required | Example | Notes |
|---|---|---|---|
APP_ENV |
yes | prod |
dev, stage, prod |
PORT |
yes | 8080 |
HTTP port |
STATIC_DIR |
yes | frontend/dist |
for ServeDir |
DB_URL |
yes | postgres://... |
SeaORM primary |
DB_RO_URL |
no | postgres://... |
read-only connector |
REDIS_URL |
no | redis://... |
rate limit/cache |
RATE_RPS |
yes | 5 |
global default req/sec/IP |
CORS_ORIGINS |
yes | https://app.example.com |
CSV |
TLS_MIN |
no | 1.3 |
enforce TLS 1.3 when terminated at app |
[BE-RUST]pub struct CoreRoutes;
impl CoreRoutes {
pub const API_BASE: &'static str = "/api/";
pub const SITEMAP: &'static str = "/sitemap.xml";
pub const ROBOTS: &'static str = "/robots.txt";
pub const HEALTH: &'static str = "/healthz";
pub const NONCE: &'static str = "/nonce";
}
[MOBILE].env.kmm per build type.Accept: application/json.X-Request-Id (UUIDv4), X-Nonce when posting forms.401 once; on second 401 force logout.429, implement exponential backoff: 1s, 2s, 4s, cap 30s. Respect Retry-After.\n where allowed. Normalize Unicode NFC./api/ for 5 min.{screen, action, http_code, latency_ms} only.[FE]frontend/dist.index.html, robots.txt, sitemap.xml. No client routing leaks. 404 handled by backend fallback.Content-Security-Policy with injected nonce for inline scripts.Referrer-Policy: strict-origin-when-cross-originX-Content-Type-Options: nosniffStrict-Transport-Security if TLS terminates at app.[BE-RUST]AppState holds: DB pools (RW/RO), Redis, config, clock, logger.ServeDir(STATIC_DIR) at /.CoreRoutes.trace_id, method, path, latency.Pseudocode
let app = Router::new()
.route(CoreRoutes::API_BASE, get(api_meta))
.route(CoreRoutes::HEALTH, get(health))
.route(CoreRoutes::NONCE, get(nonce))
.route(CoreRoutes::SITEMAP, get(sitemap))
.route(CoreRoutes::ROBOTS, get(robots))
.fallback_service(get(fallback_404))
.layer(cors_layer)
.layer(rate_limit_layer)
.layer(trace_layer)
.with_state(app_state);
Nonce
nonce = rand::thread_rng().fill(bytes[24..32]) → base64url.ip:nonce.[BE-RUST]Content-Type on API.Authorization, Cookie, Set-Cookie, X-Nonce.[BE-RUST]trace_id surfaced to clients.GET /healthz returns {ok:true, time, deps:{db:"up"/"down", redis:"up"/"down"}}.[BE-RUST]/api/ and /nonce.[BE-DB]Namespaces:
rl:{ip} → rate limit countersnonce:{ip}:{nonce} → TTL 300sEviction: allkeys-lru. Memory cap sized in ops docs.
If nonce evicted early, client must retry /nonce fetch.
X-Nonce on mutating requests to other modules that require it..env must be rotated and never committed to version control.trace_id propagated across logs, metrics, and traces for correlation.[BE-RUST]/healthz probes DB/Redis with timeouts.[BE-RUST][BE-DB]CORS_ORIGINS./api/* unknowns.[MOBILE]Retry-After.[FE][BE-DB][MOBILE]core-api KMM client with:
getApiMeta(), getNonce()Demo screen: shows API version and nonce fetch result.
[FE]robots.txt, sitemap.xml, index.html in frontend/dist.X-Request-Id.[BE-RUST]core/api/constants.rs, core/api/routes.rs, core/api/handlers.rscore/shared/error.rs, core/shared/rate_limit.rs, core/shared/telemetry.rsCoreRoutes constants as above.[BE-DB]RATE_RPS.deps.db and deps.redis as up under nominal conditions./api/v1/) for breaking changes.