feat(cosmobiologia-server): server HTTP single-user con CRUD completo (fase 2)

Crate nuevo `cosmobiologia-server` (binario axum, nativo) que
monta `cosmobiologia-engine` + `cosmobiologia-store` y expone
la rueda + el CRUD del tree por HTTP.

Endpoints v1:
- `GET  /api/health`
- `GET  /api/tree`                         tree completo anidado
- `POST /api/groups`                       crear grupo
- `PATCH /api/groups/:id`                  renombrar
- `DELETE /api/groups/:id`                 borrar
- `POST /api/contacts`                     crear contacto
- `PATCH /api/contacts/:id`                renombrar
- `DELETE /api/contacts/:id`               borrar
- `POST /api/charts`                       crear carta
- `GET  /api/charts/:id`                   chart JSON
- `PATCH /api/charts/:id`                  editar (label/birth/config)
- `DELETE /api/charts/:id`                 borrar
- `GET  /api/charts/:id/render`            RenderModel JSON
- `GET  /api/charts/:id/svg`               SVG inline (reusa
                                            svg_export del engine)
- `GET  /api/sky`                          "Cielo ahora" — RenderModel
                                            UTC actual sin chart_id real

Query params del render para activar overlays sin POST:
- `offset_min=<i64>`                       time scrubbing
- `transit=1`                              overlay de tránsito al now
- `prog_age=<f64>`                         progresión secundaria
- `sa_age=<f64>`                           solar arc
- `pd_age=<f64>`                           primary directions (Naibod)

Decisiones:
- Single-user, sin auth. Bind por default a `127.0.0.1:8787` —
  el server NO debe exponerse a la red pública en esta fase.
- DB por default = misma del desktop (`$XDG_DATA_HOME/cosmobiologia/
  charts.db`). `--db` permite override.
- CORS permissive (es localhost, single-user, sin auth).
- `ApiError` con mapeo a HTTP status: 404 NotFound,
  400 BadRequest, 500 todo lo demás. Body JSON `{ "error": "..." }`.

Smoke test:
  cargo run -p cosmobiologia-server -- --port 18787
  curl /api/health         → {"status":"ok",...}
  curl POST /api/groups    → {"id":"01KRYVP...","name":"Familia",...}
  curl POST /api/contacts  → {"id":"01KRYVP...","group_id":...}
  curl /api/tree           → árbol anidado
  curl /api/sky            → RenderModel con VSOP real

Pendiente (fase 3): cliente `cosmobiologia-web` (cdylib WASM)
que consuma estos endpoints y pinte SVG/Canvas2D.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-19 00:55:51 +00:00
parent 9b12958660
commit d341004f59
4 changed files with 681 additions and 0 deletions
Generated
+117
View File
@@ -870,6 +870,61 @@ dependencies = [
"arrayvec 0.7.6",
]
[[package]]
name = "axum"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "backtrace"
version = "0.3.76"
@@ -2248,6 +2303,26 @@ dependencies = [
"serde",
]
[[package]]
name = "cosmobiologia-server"
version = "0.1.0"
dependencies = [
"axum",
"clap",
"cosmobiologia-engine",
"cosmobiologia-model",
"cosmobiologia-render",
"cosmobiologia-store",
"directories",
"serde",
"serde_json",
"thiserror 2.0.18",
"tokio",
"tower-http",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "cosmobiologia-store"
version = "0.1.0"
@@ -4917,12 +4992,24 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "http-range-header"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.3.0"
@@ -4943,6 +5030,7 @@ dependencies = [
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"smallvec",
@@ -6571,6 +6659,12 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "matrixmultiply"
version = "0.3.10"
@@ -9955,6 +10049,17 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [
"itoa",
"serde",
"serde_core",
]
[[package]]
name = "serde_repr"
version = "0.1.20"
@@ -11551,6 +11656,7 @@ dependencies = [
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
@@ -11561,13 +11667,23 @@ checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
dependencies = [
"bitflags 2.11.1",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower",
"tower-layer",
"tower-service",
"tracing",
"url",
]
@@ -11589,6 +11705,7 @@ version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",