Share upstream definitions in @4nk/smart-ide-upstreams, systemd user units

- Add packages/smart-ide-upstreams (versioned dist) for resolveUpstream + listUpstreamKeys
- Wire smart-ide-global-api and smart-ide-sso-gateway via file: dependency
- Add systemd user unit templates and install-smart-ide-gateway-systemd-user.sh (SSO After/Requires global API)
- Update docs and VERSION 0.0.3
This commit is contained in:
Nicolas Cantu 2026-04-04 15:37:58 +02:00
parent 0af507143a
commit 940cf59178
37 changed files with 347 additions and 22 deletions

View File

@ -1 +1 @@
0.0.2
0.0.3

View File

@ -1,5 +1,7 @@
# Configuration locale (`config/`)
- **`services.local.env.example`** : variables denvironnement agrégées pour les micro-services (ports sur `127.0.0.1`, jetons, URL de lAPI globale et du SSO). Copier vers **`services.local.env`** (gitignoré à la racine du monorepo).
- **`services.local.env.example`** : variables denvironnement agrégées pour les micro-services (ports sur `127.0.0.1`, jetons, URL de lAPI globale et du SSO). Copier vers **`services.local.env`** (gitignoré à la racine du monorepo). Référencé par les unités systemd utilisateur décrites dans [docs/repo/systemd-units.md](../docs/repo/systemd-units.md).
- **Paquet partagé des amonts** : `packages/smart-ide-upstreams/` — une seule définition des clés `orchestrator`, `repos_devtools`, etc.
Voir aussi [docs/README.md](../docs/README.md).

View File

@ -47,6 +47,10 @@ Fichier **`.logs/global-api/access.log`** : lignes JSON (`ts`, `method`, `path`,
Jetons et hôtes des micro-services : mêmes noms que dans `config/services.local.env.example`.
## Source des amonts
Les clés et la résolution `host:port` / jetons sont définies dans le paquet partagé **`packages/smart-ide-upstreams/`** (`@4nk/smart-ide-upstreams`). Toute nouvelle clé damont doit y être ajoutée une seule fois, puis `npm run build` dans ce paquet et commit du répertoire `dist/`.
## Voir aussi
- [sso-gateway-api.md](./sso-gateway-api.md)

View File

@ -55,7 +55,7 @@ Aucun stockage d**utilisateurs** ou de **comptes par projet** dans ce service
| `GLOBAL_API_INTERNAL_TOKEN` | Obligatoire — même valeur que sur smart-ide-global-api |
| `SMART_IDE_MONOREPO_ROOT` | Optionnel — racine pour écrire sous `.logs/sso-gateway/` |
Les jetons et hôtes des micro-services sont lus par **smart-ide-global-api** ; voir `config/services.local.env.example` et [global-api.md](./global-api.md).
Les jetons et hôtes des micro-services sont lus par **smart-ide-global-api** ; la liste des clés `GET /v1/upstreams` provient du module **`@4nk/smart-ide-upstreams`** (`packages/smart-ide-upstreams/`). Voir `config/services.local.env.example` et [global-api.md](./global-api.md).
## Voir aussi

View File

@ -8,6 +8,7 @@ Index principal. Les **fonctionnalités** détaillées sont dans [`features/`](.
|---------|------|
| [config/services.local.env.example](../config/services.local.env.example) | Ports, jetons, `SMART_IDE_MONOREPO_ROOT` — copier vers `config/services.local.env` |
| [config/README.md](../config/README.md) | Rôle du répertoire `config/` |
| [packages/smart-ide-upstreams/README.md](../packages/smart-ide-upstreams/README.md) | Clés damont HTTP partagées (`@4nk/smart-ide-upstreams`) pour lAPI globale et le SSO |
## Documentation du dépôt (`repo/`)

View File

@ -50,7 +50,7 @@ Un **client OAuth par env** (test / pprod / prod) ou un seul client avec **claim
## Références internes
- [sso-gateway-service.md](./sso-gateway-service.md) — passerelle OIDC → API internes
- [sso-gateway-service.md](./sso-gateway-service.md) — passerelle OIDC → **smart-ide-global-api** → micro-services
- [platform-target.md](../platform-target.md) — matrice test / pprod / prod
- [deployment-target.md](../deployment-target.md) — TLS, pas de HTTP de contournement

View File

@ -30,7 +30,7 @@ Les services amont peuvent sen servir pour du **journal** ou des **règles fi
## Comptes, projets et bases métier
La passerelle **ne conserve pas** de comptes utilisateurs, de profils projet, ni de quotas métier : elle ne fait que **vérifier** le JWT OIDC et **relayer** vers les micro-services.
La passerelle **ne conserve pas** de comptes utilisateurs, de profils projet, ni de quotas métier : elle ne fait que **vérifier** le JWT OIDC et **relayer** vers **smart-ide-global-api**, qui applique les jetons techniques et proxifie vers chaque micro-service.
Les **comptes**, droits par **projet**, abonnements, historiques et toute persistance **métier** liée à lidentité restent dans les **bases des applications** (ex. docv, Enso, autres produits) et dans leurs schémas de données — pas dans `smart-ide-sso-gateway`. Le découpage par projet côté IDE et chemins de déploiement est décrit sous `projects/<id>/conf.json` — [repo/projects-directory.md](../repo/projects-directory.md).
@ -40,5 +40,6 @@ Les services amont qui reçoivent `X-OIDC-Sub` / `X-OIDC-Email` sont responsable
- [API/sso-gateway-api.md](../API/sso-gateway-api.md)
- [API/global-api.md](../API/global-api.md)
- [packages/smart-ide-upstreams/README.md](../../packages/smart-ide-upstreams/README.md) — clés damont partagées (`@4nk/smart-ide-upstreams`)
- [services/smart-ide-sso-gateway/README.md](../../services/smart-ide-sso-gateway/README.md)
- [services/smart-ide-global-api/README.md](../../services/smart-ide-global-api/README.md)

View File

@ -43,6 +43,7 @@ Toute la documentation **opérationnelle** qui vivait auparavant sous des `READM
| [service-smart-ide-tools-bridge.md](./service-smart-ide-tools-bridge.md) | Pont HTTP IDE + outils sous-modules |
| [service-smart-ide-global-api.md](./service-smart-ide-global-api.md) | API HTTP interne : proxy vers micro-services (Bearer partagé avec SSO) |
| [service-smart-ide-sso-gateway.md](./service-smart-ide-sso-gateway.md) | Passerelle OIDC utilisateur → API globale → micro-services |
| [../packages/smart-ide-upstreams/README.md](../packages/smart-ide-upstreams/README.md) | Paquet `@4nk/smart-ide-upstreams` : liste des clés et résolution des URL / jetons |
| [extension-anythingllm-workspaces.md](./extension-anythingllm-workspaces.md) | Extension AnythingLLM IDE (supprimée ; anythingllm-devtools) |
Les **spécifications** détaillées (contrats HTTP, sécurité, orchestration) restent dans [../API/README.md](../API/README.md) et [../features/](../features/).

View File

@ -1,6 +1,6 @@
# Service smart-ide-global-api (`services/smart-ide-global-api/`)
Couche HTTP **interne** : proxy vers les micro-services avec jetons techniques, **sans OIDC**. Consommée exclusivement par **`smart-ide-sso-gateway`** (Bearer `GLOBAL_API_INTERNAL_TOKEN`).
Couche HTTP **interne** : proxy vers les micro-services avec jetons techniques, **sans OIDC**. **`smart-ide-sso-gateway`** lappelle avec `GLOBAL_API_INTERNAL_TOKEN` ; des **scripts M2M** peuvent aussi utiliser le même Bearer pour un point dentrée unique (voir [sso-gateway-service.md](../features/sso-gateway-service.md)).
## Configuration locale
@ -11,6 +11,10 @@ Couche HTTP **interne** : proxy vers les micro-services avec jetons techniques,
Démarrer **avant** la passerelle SSO. Voir **[`services/smart-ide-global-api/README.md`](../../services/smart-ide-global-api/README.md)** et **[`docs/API/global-api.md`](../API/global-api.md)**.
**Liste des amonts** : source unique dans **`packages/smart-ide-upstreams/`** (import `@4nk/smart-ide-upstreams` côté global-api et SSO).
**systemd (utilisateur)** : gabarits `systemd/user/smart-ide-global-api.service.in` et `smart-ide-sso-gateway.service.in` ; installation — [systemd-units.md](./systemd-units.md), script `scripts/install-smart-ide-gateway-systemd-user.sh`.
## Voir aussi
- [service-smart-ide-sso-gateway.md](./service-smart-ide-sso-gateway.md)

View File

@ -11,6 +11,8 @@ Passerelle HTTP : validation **JWT utilisateur** (issuer docv / Enso), puis **pr
Voir **[`services/smart-ide-sso-gateway/README.md`](../../services/smart-ide-sso-gateway/README.md)**, **[`docs/features/sso-gateway-service.md`](../features/sso-gateway-service.md)** et **[`docs/API/sso-gateway-api.md`](../API/sso-gateway-api.md)**.
**systemd (utilisateur)** : lunité SSO déclare **`After=`** et **`Requires=smart-ide-global-api.service`** — [systemd-units.md](./systemd-units.md), `scripts/install-smart-ide-gateway-systemd-user.sh`.
## Voir aussi
- [service-smart-ide-global-api.md](./service-smart-ide-global-api.md)

View File

@ -46,6 +46,22 @@ Tirage **périodique** des dépôts listés dans `projects/*/conf.json` (voir [c
- Installation : `scripts/install-git-pull-systemd-user.sh` (écrit dans `~/.config/systemd/user/`, **sans** `sudo`)
- Configuration : `cron/config.env`
## smart-ide-global-api et smart-ide-sso-gateway (utilisateur)
Unités **user** pour lagrégateur HTTP interne puis la passerelle OIDC. Lunité SSO déclare **`Requires=smart-ide-global-api.service`** et **`After=smart-ide-global-api.service`** pour garantir lordre de démarrage.
- Gabarits : `systemd/user/smart-ide-global-api.service.in`, `systemd/user/smart-ide-sso-gateway.service.in`
- Variables : `config/services.local.env` (copie de `config/services.local.env.example`, gitignoré) — `GLOBAL_API_INTERNAL_TOKEN`, `OIDC_ISSUER`, jetons micro-services, etc.
- Prérequis : `npm ci && npm run build` dans `packages/smart-ide-upstreams`, `services/smart-ide-global-api`, `services/smart-ide-sso-gateway`
Installation :
```bash
./scripts/install-smart-ide-gateway-systemd-user.sh
systemctl --user start smart-ide-global-api smart-ide-sso-gateway
systemctl --user status smart-ide-global-api smart-ide-sso-gateway
```
## Linger (session fermée)
Les timers **user** ne tournent en général que lorsquune session utilisateur systemd est active. Pour exécuter les timers après déconnexion graphique complète, activer le **linger** pour lutilisateur : `loginctl enable-linger <user>` (décision dadministration machine).

View File

@ -45,6 +45,9 @@ Conséquences :
| `services/ia-dev-gateway/` | Gateway HTTP (stub runner) : registre agents `.md`, runs, SSE — [features/ia-dev-service.md](./features/ia-dev-service.md) |
| `services/smart-ide-orchestrator/` | Routage intentions (stub forward) — [features/orchestrator-api.md](./features/orchestrator-api.md) |
| `services/smart-ide-tools-bridge/` | API IDE : registre des services + Carbonyl / PageIndex / Chandra — [repo/service-smart-ide-tools-bridge.md](./repo/service-smart-ide-tools-bridge.md) |
| `services/smart-ide-global-api/` | Agrégateur HTTP interne (Bearer partagé avec le SSO) → micro-services avec jetons techniques — [repo/service-smart-ide-global-api.md](./repo/service-smart-ide-global-api.md) |
| `services/smart-ide-sso-gateway/` | Validation JWT utilisateur (docv / Enso) puis proxy via lAPI globale — [repo/service-smart-ide-sso-gateway.md](./repo/service-smart-ide-sso-gateway.md) |
| `packages/smart-ide-upstreams/` | Module partagé : clés damont et `resolveUpstream()` pour lAPI globale et la liste `GET /v1/upstreams` du SSO — [packages/smart-ide-upstreams/README.md](../packages/smart-ide-upstreams/README.md) |
| `config/` | Configuration locale agrégée (`services.local.env.example`) pour lIDE et les services |
## Environnements test, pprod, prod

View File

@ -0,0 +1 @@
node_modules/

View File

@ -0,0 +1,7 @@
# @4nk/smart-ide-upstreams
Module partagé : **`listUpstreamKeys()`**, **`resolveUpstream(key)`** et types associés. Consommé par **`services/smart-ide-global-api`** (proxy HTTP) et **`services/smart-ide-sso-gateway`** (liste exposée à `GET /v1/upstreams`).
Une seule source pour les clés et les variables denvironnement des amonts.
Le répertoire **`dist/`** est versionné pour que `npm ci` dans les services suffise sans étape préalable. Après modification de `src/`, exécuter dans ce paquet : `npm ci && npm run build`, puis committer `dist/` avec le TypeScript.

View File

@ -0,0 +1,2 @@
export { resolveUpstream, listUpstreamKeys, type UpstreamAuth, type UpstreamTarget, } from "./upstreams.js";
//# sourceMappingURL=index.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC"}

View File

@ -0,0 +1 @@
export { resolveUpstream, listUpstreamKeys, } from "./upstreams.js";

View File

@ -0,0 +1,15 @@
export type UpstreamAuth = {
kind: "bearer";
token: string;
} | {
kind: "header";
name: string;
value: string;
};
export type UpstreamTarget = {
baseUrl: string;
auth: UpstreamAuth;
};
export declare const resolveUpstream: (key: string) => UpstreamTarget | null;
export declare const listUpstreamKeys: () => string[];
//# sourceMappingURL=upstreams.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"upstreams.d.ts","sourceRoot":"","sources":["../src/upstreams.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAMF,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,cAAc,GAAG,IAsE9D,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,MAAM,EAUzC,CAAC"}

View File

@ -0,0 +1,68 @@
const trimSlash = (s) => s.replace(/\/+$/, "");
const env = (k, d) => process.env[k]?.trim() ?? d;
export const resolveUpstream = (key) => {
switch (key) {
case "orchestrator":
return {
baseUrl: trimSlash(`http://${env("ORCHESTRATOR_HOST", "127.0.0.1")}:${env("ORCHESTRATOR_PORT", "37145")}`),
auth: { kind: "bearer", token: env("ORCHESTRATOR_TOKEN", "") },
};
case "repos_devtools":
return {
baseUrl: trimSlash(`http://${env("REPOS_DEVTOOLS_HOST", "127.0.0.1")}:${env("REPOS_DEVTOOLS_PORT", "37140")}`),
auth: { kind: "bearer", token: env("REPOS_DEVTOOLS_TOKEN", "") },
};
case "ia_dev_gateway":
return {
baseUrl: trimSlash(`http://${env("IA_DEV_GATEWAY_HOST", "127.0.0.1")}:${env("IA_DEV_GATEWAY_PORT", "37144")}`),
auth: { kind: "bearer", token: env("IA_DEV_GATEWAY_TOKEN", "") },
};
case "anythingllm_devtools":
return {
baseUrl: trimSlash(`http://${env("ANYTHINGLLM_DEVTOOLS_HOST", "127.0.0.1")}:${env("ANYTHINGLLM_DEVTOOLS_PORT", "37146")}`),
auth: { kind: "bearer", token: env("ANYTHINGLLM_DEVTOOLS_TOKEN", "") },
};
case "tools_bridge":
return {
baseUrl: trimSlash(`http://${env("TOOLS_BRIDGE_HOST", "127.0.0.1")}:${env("TOOLS_BRIDGE_PORT", "37147")}`),
auth: { kind: "bearer", token: env("TOOLS_BRIDGE_TOKEN", "") },
};
case "langextract":
return {
baseUrl: trimSlash(`http://${env("LANGEXTRACT_API_HOST", "127.0.0.1")}:${env("LANGEXTRACT_API_PORT", "37141")}`),
auth: { kind: "bearer", token: env("LANGEXTRACT_SERVICE_TOKEN", "") },
};
case "regex_search":
return {
baseUrl: trimSlash(`http://${env("REGEX_SEARCH_HOST", "127.0.0.1")}:${env("REGEX_SEARCH_PORT", "37143")}`),
auth: { kind: "bearer", token: env("REGEX_SEARCH_TOKEN", "") },
};
case "claw_proxy":
return {
baseUrl: trimSlash(`http://${env("CLAW_PROXY_HOST", "127.0.0.1")}:${env("CLAW_PROXY_PORT", "37142")}`),
auth: { kind: "bearer", token: env("CLAW_PROXY_TOKEN", "") },
};
case "local_office":
return {
baseUrl: trimSlash(env("LOCAL_OFFICE_URL", "http://127.0.0.1:8000")),
auth: {
kind: "header",
name: "X-API-Key",
value: env("LOCAL_OFFICE_API_KEY", ""),
},
};
default:
return null;
}
};
export const listUpstreamKeys = () => [
"orchestrator",
"repos_devtools",
"ia_dev_gateway",
"anythingllm_devtools",
"tools_bridge",
"langextract",
"regex_search",
"claw_proxy",
"local_office",
];

View File

@ -0,0 +1,51 @@
{
"name": "@4nk/smart-ide-upstreams",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@4nk/smart-ide-upstreams",
"version": "0.1.0",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@types/node": {
"version": "20.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",
"integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
}
}
}

View File

@ -0,0 +1,26 @@
{
"name": "@4nk/smart-ide-upstreams",
"version": "0.1.0",
"private": true,
"description": "Shared upstream keys and resolveUpstream() for smart-ide-global-api and smart-ide-sso-gateway.",
"license": "MIT",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"scripts": {
"build": "tsc -p ."
},
"engines": {
"node": ">=20"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
}
}

View File

@ -0,0 +1,6 @@
export {
resolveUpstream,
listUpstreamKeys,
type UpstreamAuth,
type UpstreamTarget,
} from "./upstreams.js";

View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"declaration": true,
"declarationMap": true
},
"include": ["src/**/*.ts"]
}

View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Installe les unités systemd *utilisateur* pour smart-ide-global-api puis smart-ide-sso-gateway.
# Prérequis : config/services.local.env (copie de config/services.local.env.example), builds npm
# (packages/smart-ide-upstreams, services/smart-ide-global-api, services/smart-ide-sso-gateway).
# Usage : ./scripts/install-smart-ide-gateway-systemd-user.sh
# Puis : systemctl --user start smart-ide-global-api smart-ide-sso-gateway
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
GLOBAL_IN="${ROOT}/systemd/user/smart-ide-global-api.service.in"
SSO_IN="${ROOT}/systemd/user/smart-ide-sso-gateway.service.in"
GLOBAL_OUT="${UNIT_DIR}/smart-ide-global-api.service"
SSO_OUT="${UNIT_DIR}/smart-ide-sso-gateway.service"
mkdir -p "$UNIT_DIR"
sed "s|@SMART_IDE_ROOT@|$ROOT|g" "$GLOBAL_IN" >"$GLOBAL_OUT"
sed "s|@SMART_IDE_ROOT@|$ROOT|g" "$SSO_IN" >"$SSO_OUT"
chmod 0644 "$GLOBAL_OUT" "$SSO_OUT"
systemctl --user daemon-reload
systemctl --user enable smart-ide-global-api.service
systemctl --user enable smart-ide-sso-gateway.service
echo "Unités : $GLOBAL_OUT"
echo " $SSO_OUT"
echo "Démarrage : systemctl --user start smart-ide-global-api smart-ide-sso-gateway"
echo "État : systemctl --user status smart-ide-global-api smart-ide-sso-gateway"

View File

@ -20,6 +20,8 @@ npm start
Écoute par défaut : `http://127.0.0.1:37149`.
**Amonts** : module **`@4nk/smart-ide-upstreams`** (`../../packages/smart-ide-upstreams/`). Après modification des clés ou des variables denvironnement mappées, reconstruire ce paquet et committer son `dist/`.
## Journaux
Une ligne JSON par requête (hors `GET /health`) dans **`.logs/global-api/access.log`** (répertoire `.logs/` à la racine du monorepo, créé au besoin).

View File

@ -8,6 +8,9 @@
"name": "@4nk/smart-ide-global-api",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@4nk/smart-ide-upstreams": "file:../../packages/smart-ide-upstreams"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
@ -16,6 +19,22 @@
"node": ">=20"
}
},
"../../packages/smart-ide-upstreams": {
"name": "@4nk/smart-ide-upstreams",
"version": "0.1.0",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@4nk/smart-ide-upstreams": {
"resolved": "../../packages/smart-ide-upstreams",
"link": true
},
"node_modules/@types/node": {
"version": "20.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",

View File

@ -13,6 +13,9 @@
"engines": {
"node": ">=20"
},
"dependencies": {
"@4nk/smart-ide-upstreams": "file:../../packages/smart-ide-upstreams"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"

View File

@ -1,6 +1,10 @@
import * as http from "node:http";
import {
listUpstreamKeys,
resolveUpstream,
type UpstreamAuth,
} from "@4nk/smart-ide-upstreams";
import { appendGlobalApiAccessLog } from "./accessLog.js";
import { listUpstreamKeys, resolveUpstream, type UpstreamAuth } from "./upstreams.js";
const HOST = process.env.GLOBAL_API_HOST ?? "127.0.0.1";
const PORT = Number(process.env.GLOBAL_API_PORT ?? "37149");

View File

@ -6,7 +6,7 @@ HTTP gateway that validates **user** access tokens from the docv / Enso OIDC iss
- Verify `Authorization: Bearer <access_token>` with JWKS (`OIDC_ISSUER`, optional `OIDC_AUDIENCE`, optional `OIDC_JWKS_URI`).
- Expose `GET /health` without auth.
- Expose `GET /v1/token/verify` and `GET /v1/upstreams` with user Bearer.
- Expose `GET /v1/token/verify` and `GET /v1/upstreams` with user Bearer (upstream keys from **`@4nk/smart-ide-upstreams`**).
- Proxy `ANY /proxy/<upstream_key>/<path>` to **smart-ide-global-api** (`GLOBAL_API_URL`, `GLOBAL_API_INTERNAL_TOKEN`), which relays to the target service and adds upstream auth plus `X-OIDC-Sub` / `X-OIDC-Email` when present in the JWT.
Structured request logs (except `GET /health` and `OPTIONS`) are appended to **`.logs/sso-gateway/access.log`** under the monorepo root.

View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@4nk/smart-ide-upstreams": "file:../../packages/smart-ide-upstreams",
"jose": "^5.9.6"
},
"devDependencies": {
@ -19,6 +20,22 @@
"node": ">=20"
}
},
"../../packages/smart-ide-upstreams": {
"name": "@4nk/smart-ide-upstreams",
"version": "0.1.0",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@4nk/smart-ide-upstreams": {
"resolved": "../../packages/smart-ide-upstreams",
"link": true
},
"node_modules/@types/node": {
"version": "20.19.39",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",

View File

@ -2,7 +2,7 @@
"name": "@4nk/smart-ide-sso-gateway",
"version": "0.1.0",
"private": true,
"description": "OIDC JWT validation (docv/Enso IdP) and authenticated proxy to smart_ide micro-services.",
"description": "OIDC JWT validation (docv/Enso IdP); proxies via smart-ide-global-api to smart_ide micro-services.",
"license": "MIT",
"type": "module",
"main": "dist/server.js",
@ -14,6 +14,7 @@
"node": ">=20"
},
"dependencies": {
"@4nk/smart-ide-upstreams": "file:../../packages/smart-ide-upstreams",
"jose": "^5.9.6"
},
"devDependencies": {

View File

@ -2,7 +2,7 @@ import * as http from "node:http";
import type { JWTPayload } from "jose";
import { appendSsoAccessLog } from "./accessLog.js";
import { discoverJwksUri, createVerify, type VerifyFn } from "./oidc.js";
import { listUpstreamKeys } from "./upstreams.js";
import { listUpstreamKeys } from "@4nk/smart-ide-upstreams";
const HOST = process.env.SSO_GATEWAY_HOST ?? "127.0.0.1";
const PORT = Number(process.env.SSO_GATEWAY_PORT ?? "37148");

View File

@ -1,12 +0,0 @@
/** Upstream keys exposed to OIDC-authenticated clients; traffic is relayed via smart-ide-global-api. */
export const listUpstreamKeys = (): string[] => [
"orchestrator",
"repos_devtools",
"ia_dev_gateway",
"anythingllm_devtools",
"tools_bridge",
"langextract",
"regex_search",
"claw_proxy",
"local_office",
];

View File

@ -0,0 +1,16 @@
[Unit]
Description=smart_ide — API globale interne (proxy vers micro-services, jetons techniques)
Documentation=file://@SMART_IDE_ROOT@/docs/repo/service-smart-ide-global-api.md
After=network-online.target
[Service]
Type=simple
WorkingDirectory=@SMART_IDE_ROOT@/services/smart-ide-global-api
# Fichier agrégé (gitignoré) : copier config/services.local.env.example vers config/services.local.env
EnvironmentFile=-@SMART_IDE_ROOT@/config/services.local.env
ExecStart=/usr/bin/node @SMART_IDE_ROOT@/services/smart-ide-global-api/dist/server.js
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target

View File

@ -0,0 +1,17 @@
[Unit]
Description=smart_ide — passerelle SSO OIDC (délègue le proxy à smart-ide-global-api)
Documentation=file://@SMART_IDE_ROOT@/docs/repo/service-smart-ide-sso-gateway.md
After=network-online.target
After=smart-ide-global-api.service
Requires=smart-ide-global-api.service
[Service]
Type=simple
WorkingDirectory=@SMART_IDE_ROOT@/services/smart-ide-sso-gateway
EnvironmentFile=-@SMART_IDE_ROOT@/config/services.local.env
ExecStart=/usr/bin/node @SMART_IDE_ROOT@/services/smart-ide-sso-gateway/dist/server.js
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target