Skip to content

feat(portal): GhostAuth resource-server + bento widget endpoints - #50

Merged
ClaraVnk merged 2 commits into
mainfrom
feat/portal-resource-server
Jul 3, 2026
Merged

feat(portal): GhostAuth resource-server + bento widget endpoints#50
ClaraVnk merged 2 commits into
mainfrom
feat/portal-resource-server

Conversation

@ClaraVnk

@ClaraVnk ClaraVnk commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Contexte

Pilote de l'intégration ghostboard pour la suite. GhostMonitor devient un app portail de premier plan : il publie un manifeste GhostApp et deux data_url que le portail rend, protégés par les access tokens GhostAuth (modèle resource-server léger validé avec l'équipe).

Changements

  • core/security/resource_server.py — valide un token GhostAuth (JWKS + iss + aud, RS256/ES256/EdDSA). Calqué sur ghostboard ; EdDSA via joserfc (python-jose ne le supporte pas). Discovery + JWKS cachés.
  • api/deps/portal.pyrequire_portal_token : extrait le bearer, le vérifie, exige l'entitlement ghostsuite:ghostmon (scope ∪ groups), mappe le sub au User local via oidc_subject. Pas de JIT-provisioning (sub inconnu → widget vide → la tuile s'auto-masque).
  • api/routes/widgets.pyGET /api/v1/widgets/{uptime,latency} : stat « services up » + chart latence récente, scopés à l'utilisateur, au format du contrat widget ghostboard.
  • /.well-known/ghostapp.yaml — manifeste public (icon omis pour que le portail garde son icône same-origin sous sa CSP).
  • OIDC_AUDIENCE (défaut = client id). Seules ces routes portail acceptent un token GhostAuth ; l'UI/API de l'app gardent les sessions locales.

Vérification (bout en bout, contrat)

Cross-check contre le vrai loader ghostboard : le manifeste valide, se merge (icon/auth épinglés au stub), les data_url correspondent au registry, et les payloads passent normalize_widget_payload.

  • 12 tests (validateur RS256/EdDSA + rejet aud/iss/exp ; gate token, gate entitlement, scoping par user, vide si sub inconnu, manifeste public).
  • Suite complète : 247 verts, ruff + mypy strict clean.
  • Non couvert : run live contre GhostAuth+ghostboard déployés (staging).

Suite

Patron réutilisable → réplication sur ghostlink/ghostbit, et version « compteur only » pour les apps ZK (ghostcal/ghostmail/ghostpass).

ClaraVnk added 2 commits July 3, 2026 14:55
Makes GhostMonitor a first-class ghostboard portal app: it now serves a public
GhostApp manifest and two widget data_urls the portal renders, gated by GhostAuth
access tokens.

- core/security/resource_server.py: validates a GhostAuth access token (JWKS +
  issuer + audience, RS256/ES256/EdDSA — mirrors ghostboard, EdDSA-capable via
  joserfc). Discovery + JWKS cached.
- api/deps/portal.py: require_portal_token — extracts the bearer, verifies it,
  requires the ghostsuite:ghostmon entitlement (scope ∪ groups), and maps the
  token subject to the local user via oidc_subject (no JIT provisioning).
- api/routes/widgets.py: GET /api/v1/widgets/{uptime,latency} — per-user
  services-up stat and recent-latency chart, in ghostboard's widget contract.
- /.well-known/ghostapp.yaml: public manifest (icon omitted so the portal keeps
  its same-origin icon under its CSP). Cross-checked against ghostboard's loader:
  validates, merges, data_urls + payloads accepted.
- OIDC_AUDIENCE setting (defaults to client id). Only these portal routes accept
  GhostAuth tokens; the app's own UI/API keep local sessions.

Tests: 12 new (validator RS256/EdDSA + aud/iss/exp rejection; route token gate,
entitlement gate, per-user scoping, empty-on-unknown-subject, public manifest).
Full suite 247 pass, ruff + mypy strict clean.
@ClaraVnk
ClaraVnk merged commit e8deed7 into main Jul 3, 2026
4 checks passed
@ClaraVnk
ClaraVnk deleted the feat/portal-resource-server branch July 3, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant