@nodefony/devkit 10.0.0-beta.2 → 10.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -5
- package/dist/_virtual/{_@oxc-project_runtime@0.152.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorate.js +1 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.152.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorateParam.js +1 -2
- package/dist/index.js +24 -11
- package/dist/nodefony/config/config.js +16 -137
- package/dist/nodefony/config/defineModuleConfig.js +1 -2
- package/dist/nodefony/controllers/DevkitController.js +7 -14
- package/dist/nodefony/controllers/McpController.js +27 -163
- package/dist/nodefony/controllers/ProfileSessionController.js +47 -0
- package/dist/nodefony/mcp/observe.js +235 -0
- package/dist/nodefony/mcp/profileReport.js +242 -0
- package/dist/nodefony/mcp/profileRoute.js +521 -0
- package/dist/nodefony/mcp/shotClient.js +84 -0
- package/dist/nodefony/mcp/shutdown.js +44 -0
- package/dist/nodefony/mcp/tools.js +696 -0
- package/dist/nodefony/service/DevkitService.js +93 -29
- package/dist/nodefony/src/card.js +1 -2
- package/dist/nodefony/src/errors/DevkitError.js +1 -2
- package/dist/nodefony/src/profileSession.js +14 -0
- package/dist/types/index.d.ts +15 -1
- package/dist/types/nodefony/config/config.d.ts +1 -1
- package/dist/types/nodefony/controllers/McpController.d.ts +13 -17
- package/dist/types/nodefony/controllers/ProfileSessionController.d.ts +31 -0
- package/dist/types/nodefony/interfaces/IDevkitService.d.ts +22 -1
- package/dist/types/nodefony/mcp/observe.d.ts +83 -0
- package/dist/types/nodefony/mcp/profileReport.d.ts +138 -0
- package/dist/types/nodefony/mcp/profileRoute.d.ts +87 -0
- package/dist/types/nodefony/mcp/shotClient.d.ts +53 -0
- package/dist/types/nodefony/mcp/shutdown.d.ts +25 -0
- package/dist/types/nodefony/mcp/tools.d.ts +109 -0
- package/dist/types/nodefony/service/DevkitService.d.ts +41 -4
- package/dist/types/nodefony/src/profileSession.d.ts +12 -0
- package/docs/index.md +217 -20
- package/package.json +17 -12
- package/skills/nodefony-add-crud/SKILL.md +5 -0
- package/skills/nodefony-add-realtime-channel/SKILL.md +66 -9
- package/skills/nodefony-add-service/SKILL.md +14 -3
- package/skills/nodefony-authentication/SKILL.md +234 -0
- package/skills/nodefony-browser/SKILL.md +65 -21
- package/skills/nodefony-browser/references/socket.md +13 -4
- package/skills/nodefony-browser/references/sondes.md +13 -0
- package/skills/nodefony-browser/scripts/audit.mjs +59 -10
- package/skills/nodefony-browser/scripts/inspect.mjs +123 -5
- package/skills/nodefony-browser/scripts/lib/browser.mjs +112 -6
- package/skills/nodefony-browser/scripts/lib/probes.mjs +219 -7
- package/skills/nodefony-browser/scripts/socket.mjs +70 -4
- package/skills/nodefony-browser/scripts/watch.mjs +101 -0
- package/skills/nodefony-dev/SKILL.md +78 -82
- package/skills/nodefony-dev/scripts/docs.mjs +24 -8
- package/skills/nodefony-devops/SKILL.md +98 -74
- package/skills/nodefony-devops/references/compose.md +8 -0
- package/skills/nodefony-devops/references/dimensionnement.md +122 -0
- package/skills/nodefony-devops/references/frontal.md +282 -48
- package/skills/nodefony-devops/references/kubernetes.md +41 -14
- package/skills/nodefony-devops/references/secrets.md +30 -5
- package/skills/nodefony-devops/references/variables.md +66 -31
- package/skills/nodefony-migrate-schema/SKILL.md +5 -2
- package/skills/nodefony-migrate-schema/references/verdicts.md +20 -19
- package/skills/nodefony-protect-route/SKILL.md +124 -21
- package/skills/nodefony-security-review/SKILL.md +127 -0
- package/skills/nodefony-security-review/scripts/review-diff.mjs +1090 -0
- package/skills/nodefony-troubleshoot/SKILL.md +225 -0
- package/skills/nodefony-troubleshoot/scripts/log-errors.mjs +465 -0
- package/skills/nodefony-upgrade/SKILL.md +130 -0
- package/dist/_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/decorateMetadata.js +0 -6
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type IMcpCaller, type IMcpTool, type IRolesWithin } from "nodefony";
|
|
2
|
+
import { type IProfilerReader } from "@nodefony/http";
|
|
3
|
+
import { type IObserveProbe } from "./observe.js";
|
|
4
|
+
import { type RequestLogs } from "./profileReport.js";
|
|
5
|
+
import { type IShotClient, type IShotTarget } from "./shotClient.js";
|
|
6
|
+
import { type OnShutdown } from "./shutdown.js";
|
|
7
|
+
/** Requêtes mesurées par défaut. */
|
|
8
|
+
export declare const PROFILE_ROUTE_DEFAULT_COUNT = 50;
|
|
9
|
+
/**
|
|
10
|
+
* Requêtes mesurées au plus. Avec la chauffe, sous les 500 profils que garde le
|
|
11
|
+
* profileur : au-delà, les premiers seraient évincés avant d'être lus.
|
|
12
|
+
*/
|
|
13
|
+
export declare const PROFILE_ROUTE_MAX_COUNT = 200;
|
|
14
|
+
/** Requêtes simultanées par défaut. */
|
|
15
|
+
export declare const PROFILE_ROUTE_DEFAULT_CONCURRENCY = 4;
|
|
16
|
+
/** Requêtes simultanées au plus : mesurer une route, pas saturer le process. */
|
|
17
|
+
export declare const PROFILE_ROUTE_MAX_CONCURRENCY = 8;
|
|
18
|
+
/** Requêtes de chauffe par défaut, tirées AVANT et hors des mesures. */
|
|
19
|
+
export declare const PROFILE_ROUTE_DEFAULT_WARMUP = 3;
|
|
20
|
+
/** Requêtes de chauffe au plus. */
|
|
21
|
+
export declare const PROFILE_ROUTE_MAX_WARMUP = 20;
|
|
22
|
+
/**
|
|
23
|
+
* Budget de temps d'un tir, en ms. Sous les 60 s qu'un client MCP attend par
|
|
24
|
+
* défaut : au-delà, l'agent couperait l'appel juste avant le rapport.
|
|
25
|
+
*/
|
|
26
|
+
export declare const PROFILE_ROUTE_BUDGET_MS = 45000;
|
|
27
|
+
/**
|
|
28
|
+
* Attente maximale, en ms, d'un profil après la réponse : le profileur le
|
|
29
|
+
* collecte au `close` de la réponse, émis en différé — rien ne garantit qu'il
|
|
30
|
+
* précède la fin de lecture côté client, dans le même process.
|
|
31
|
+
*/
|
|
32
|
+
export declare const PROFILE_COLLECT_WAIT_MS = 500;
|
|
33
|
+
/** Ce dont l'outil a besoin — injecté, pour l'éprouver sans application. */
|
|
34
|
+
export interface IProfileRouteDeps {
|
|
35
|
+
/** Le profileur de l'application, ou `undefined` hors développement. */
|
|
36
|
+
getProfiler: () => IProfilerReader | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Ce process sert-il des requêtes ? Rend `false` sous la porte stdio :
|
|
39
|
+
* l'outil le dit ({@link NOT_SERVING_MESSAGE}). Absent : supposé servir.
|
|
40
|
+
*/
|
|
41
|
+
servesTraffic?: (() => boolean) | undefined;
|
|
42
|
+
/** L'adresse d'écoute HTTP en clair de l'application, ou `null`. */
|
|
43
|
+
getTarget: () => IShotTarget | null;
|
|
44
|
+
/** Fabrique du client du tir (défaut : `node:http`, cf {@link createShotClient}). */
|
|
45
|
+
createClient?: ((target: IShotTarget, concurrency: number) => IShotClient) | undefined;
|
|
46
|
+
/** Fabrique de la sonde du process (défaut : `ProcessProbe` du cœur). */
|
|
47
|
+
createProbe?: (() => IObserveProbe) | undefined;
|
|
48
|
+
/** Émet le ticket à usage unique qui ouvrira la session de `identifier`. */
|
|
49
|
+
issueTicket?: ((identifier: string) => string) | undefined;
|
|
50
|
+
/** Détruit la session de profilage désignée par son pseudonyme. */
|
|
51
|
+
closeSession?: ((ref: string) => Promise<unknown>) | undefined;
|
|
52
|
+
/** Les rôles de `target` sont-ils inclus dans ceux de `owner` (hiérarchie comprise) ? */
|
|
53
|
+
rolesWithin?: IRolesWithin | undefined;
|
|
54
|
+
/** Lit les lignes de journal d'une requête en erreur. */
|
|
55
|
+
readRequestLogs?: ((requestId: string, caller: IMcpCaller) => Promise<RequestLogs>) | undefined;
|
|
56
|
+
/** S'abonne à l'arrêt du serveur pour la durée d'un appel. */
|
|
57
|
+
onShutdown?: OnShutdown | undefined;
|
|
58
|
+
/** Attente d'un profil après sa réponse (défaut {@link PROFILE_COLLECT_WAIT_MS}). */
|
|
59
|
+
collectWaitMs?: number | undefined;
|
|
60
|
+
/** Budget du tir (défaut {@link PROFILE_ROUTE_BUDGET_MS}). */
|
|
61
|
+
budgetMs?: number | undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Contrôle le chemin à profiler : un CHEMIN de l'application, jamais une URL —
|
|
65
|
+
* l'outil ne doit pouvoir viser qu'elle.
|
|
66
|
+
*
|
|
67
|
+
* @param raw - l'argument `path`, non fiable.
|
|
68
|
+
* @returns le chemin normalisé (fragment retiré), ou la raison du refus.
|
|
69
|
+
*/
|
|
70
|
+
export declare function checkProfilePath(raw: unknown): {
|
|
71
|
+
ok: true;
|
|
72
|
+
path: string;
|
|
73
|
+
} | {
|
|
74
|
+
ok: false;
|
|
75
|
+
reason: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* L'outil `nodefony_profile_route` : envoie lui-même N requêtes à une route de
|
|
79
|
+
* l'application, au nom d'un compte s'il le faut, et rend leur profil agrégé.
|
|
80
|
+
*
|
|
81
|
+
* Rien n'est armé hors d'un appel : le client du tir (ses connexions), la
|
|
82
|
+
* session de profilage et l'écoute de l'arrêt du serveur naissent avec l'appel
|
|
83
|
+
* et sont libérés à sa sortie, quelle qu'elle soit.
|
|
84
|
+
*
|
|
85
|
+
* @param deps - profileur, adresse d'écoute, ouverture de session, journal.
|
|
86
|
+
*/
|
|
87
|
+
export declare function profileRouteTool(deps: IProfileRouteDeps): IMcpTool;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Délai d'une requête du tir, en ms : au-delà, elle compte « sans réponse ». */
|
|
2
|
+
export declare const SHOT_REQUEST_TIMEOUT_MS = 15000;
|
|
3
|
+
/** Où l'application écoute, vue de son propre process. */
|
|
4
|
+
export interface IShotTarget {
|
|
5
|
+
/** Adresse de connexion (boucle locale). */
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
/** En-tête `Host` envoyé : le domaine que l'application attend. */
|
|
9
|
+
hostHeader: string;
|
|
10
|
+
}
|
|
11
|
+
/** Une requête du tir. */
|
|
12
|
+
export interface IShotRequest {
|
|
13
|
+
method: "GET" | "HEAD" | "POST";
|
|
14
|
+
path: string;
|
|
15
|
+
headers: Readonly<Record<string, string>>;
|
|
16
|
+
/** Lire le corps de la réponse (connexion seulement ; un tir le jette). */
|
|
17
|
+
readBody?: boolean | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Ce que le client retient d'une réponse. */
|
|
20
|
+
export interface IShotResponse {
|
|
21
|
+
status: number;
|
|
22
|
+
location: string | null;
|
|
23
|
+
setCookie: readonly string[];
|
|
24
|
+
body: string | null;
|
|
25
|
+
}
|
|
26
|
+
/** Le client d'UN tir : ses connexions vivent le temps de l'appel. */
|
|
27
|
+
export interface IShotClient {
|
|
28
|
+
send(request: IShotRequest, signal: AbortSignal): Promise<IShotResponse>;
|
|
29
|
+
/** Ferme les connexions gardées ouvertes ; les requêtes en vol échouent. */
|
|
30
|
+
close(): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Client `node:http` d'un tir : connexions gardées ouvertes entre deux requêtes,
|
|
34
|
+
* comme un navigateur, au plus `concurrency` à la fois, toutes fermées par
|
|
35
|
+
* `close()`. Un `fetch` passerait par un pool global, qui survivrait à l'appel.
|
|
36
|
+
*
|
|
37
|
+
* @param target - l'adresse d'écoute de l'application.
|
|
38
|
+
* @param concurrency - connexions simultanées au plus.
|
|
39
|
+
* @returns le client, à fermer en fin de tir.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createShotClient(target: IShotTarget, concurrency: number): IShotClient;
|
|
42
|
+
/**
|
|
43
|
+
* Lit l'adresse d'écoute du serveur HTTP en clair de l'application (service
|
|
44
|
+
* `server-http`), telle qu'il l'a réellement obtenue — port de repli compris.
|
|
45
|
+
*
|
|
46
|
+
* Une écoute sur toutes les interfaces (`0.0.0.0`, `::`) se joint par la boucle
|
|
47
|
+
* locale : c'est aussi ce qui rend l'appel LOCAL pour la route de connexion du
|
|
48
|
+
* profilage.
|
|
49
|
+
*
|
|
50
|
+
* @param server - ce que le conteneur rend pour `server-http`.
|
|
51
|
+
* @returns la cible, ou `null` si aucun serveur n'est prêt.
|
|
52
|
+
*/
|
|
53
|
+
export declare function readShotTarget(server: unknown): IShotTarget | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IMcpToolRun } from "nodefony";
|
|
2
|
+
/** Abonnement à l'arrêt du serveur, pour la durée d'UN appel d'outil. */
|
|
3
|
+
export type OnShutdown = (listener: () => Promise<void>) => () => void;
|
|
4
|
+
/** Ce qu'un outil long lit pour savoir s'il doit s'arrêter, et pourquoi. */
|
|
5
|
+
export interface IToolStop {
|
|
6
|
+
/** Avorté quand l'agent abandonne l'appel OU que le serveur s'arrête. */
|
|
7
|
+
readonly signal: AbortSignal;
|
|
8
|
+
/** `true` si c'est l'arrêt du serveur qui a clos l'appel. */
|
|
9
|
+
readonly interrupted: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Le rapport est rendu : l'arrêt du serveur, s'il attendait, reprend, et
|
|
12
|
+
* l'écouteur quitte le kernel. À appeler sur TOUS les chemins de sortie.
|
|
13
|
+
*/
|
|
14
|
+
release(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Arme l'arrêt d'un outil long : l'agent qui abandonne, ou le serveur qui
|
|
18
|
+
* s'arrête (rechargement après une modification de fichier). Dans le second
|
|
19
|
+
* cas, l'arrêt attend — borné — que le rapport partiel soit parti.
|
|
20
|
+
*
|
|
21
|
+
* @param run - l'appel en cours, porteur du signal d'abandon de l'agent.
|
|
22
|
+
* @param onShutdown - abonnement à l'arrêt du serveur ; absent hors application.
|
|
23
|
+
* @returns le signal combiné, la cause, et la libération.
|
|
24
|
+
*/
|
|
25
|
+
export declare function watchToolStop(run: IMcpToolRun | undefined, onShutdown: OnShutdown | undefined): IToolStop;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { skippedChecks } from "nodefony";
|
|
2
|
+
import type { IDoctorReport, IAdminBrokerLike, IMcpTool } from "nodefony";
|
|
3
|
+
import type { IProfilerReader } from "@nodefony/http";
|
|
4
|
+
import { type IProfileRouteDeps } from "./profileRoute.js";
|
|
5
|
+
/** Ce dont les outils INTÉGRÉS ont besoin — injecté, jamais lu ici. */
|
|
6
|
+
export interface IMcpToolDeps {
|
|
7
|
+
/** Le service `adminBroker` du conteneur, ou `undefined` s'il manque. */
|
|
8
|
+
broker: IAdminBrokerLike | undefined;
|
|
9
|
+
/** Compose la carte de visite de l'application. */
|
|
10
|
+
getCard: () => unknown;
|
|
11
|
+
/**
|
|
12
|
+
* Racine depuis laquelle lire le disque (graphe symbolique, diagnostic).
|
|
13
|
+
*
|
|
14
|
+
* Injectée plutôt que lue par `process.cwd()` : le serveur répond dans le
|
|
15
|
+
* process de l'application, dont le dossier courant n'est pas garanti être
|
|
16
|
+
* celui du projet — et un outil qui diagnostiquerait le mauvais dossier
|
|
17
|
+
* conclurait « rien à signaler » avec aplomb.
|
|
18
|
+
*/
|
|
19
|
+
projectRoot: string;
|
|
20
|
+
/**
|
|
21
|
+
* Le profileur de développement (`"profiler"` du conteneur), ou `undefined`
|
|
22
|
+
* hors développement : `nodefony_observe` le dit au lieu de planter.
|
|
23
|
+
*/
|
|
24
|
+
getProfiler: () => IProfilerReader | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Ce process sert-il des requêtes ? `false` sous la porte stdio, où les
|
|
27
|
+
* outils de MESURE refusent en le disant ; absent : supposé servir.
|
|
28
|
+
*/
|
|
29
|
+
servesTraffic?: (() => boolean) | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* S'abonne à l'arrêt du serveur pour la durée d'un appel (rapport partiel de
|
|
32
|
+
* `nodefony_observe`) ; absent hors application.
|
|
33
|
+
*/
|
|
34
|
+
onShutdown?: ((listener: () => Promise<void>) => () => void) | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Ce que `nodefony_profile_route` demande à l'application : son adresse
|
|
37
|
+
* d'écoute, l'ouverture et la fermeture de la session de profilage, la
|
|
38
|
+
* comparaison des rôles de deux comptes. Absent hors application : l'outil
|
|
39
|
+
* dit qu'il n'a rien à viser.
|
|
40
|
+
*/
|
|
41
|
+
profileRoute?: Pick<IProfileRouteDeps, "getTarget" | "issueTicket" | "closeSession" | "rolesWithin"> | undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Clés des outils intégrés — ce que l'allowlist de configuration nomme.
|
|
45
|
+
*
|
|
46
|
+
* Publiée pour qu'un schéma de configuration puisse la valider au lieu de la
|
|
47
|
+
* retaper : une clé inconnue en config est silencieusement sans effet, et
|
|
48
|
+
* l'utilisateur croit avoir activé quelque chose.
|
|
49
|
+
*/
|
|
50
|
+
export declare const BUILTIN_MCP_TOOL_KEYS: readonly ["inspect", "card", "check", "symbols", "docs", "admin_list", "admin_call", "observe", "profile_route"];
|
|
51
|
+
/** Clé d'un outil intégré. */
|
|
52
|
+
export type BuiltinMcpToolKey = (typeof BUILTIN_MCP_TOOL_KEYS)[number];
|
|
53
|
+
/** Contrôles sautés pour la MÊME raison : la raison une fois, ses familles ensuite. */
|
|
54
|
+
export interface ISkippedCheckGroup {
|
|
55
|
+
/** Famille → titre, dans l'ordre de lecture du rapport. */
|
|
56
|
+
families: Record<string, string>;
|
|
57
|
+
reason: string;
|
|
58
|
+
unlock?: string | undefined;
|
|
59
|
+
onDemand?: boolean | undefined;
|
|
60
|
+
notApplicable?: boolean | undefined;
|
|
61
|
+
advisory?: boolean | undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Regroupe les contrôles sautés qui disent exactement la même chose.
|
|
65
|
+
*
|
|
66
|
+
* Sur l'application de développement, sept familles sautées partagent trois
|
|
67
|
+
* raisons : les répéter famille par famille coûtait ~1 800 caractères à chaque
|
|
68
|
+
* appel, relus ensuite à chaque tour de l'agent.
|
|
69
|
+
*
|
|
70
|
+
* @param skipped - les contrôles sautés, dans l'ordre du rapport
|
|
71
|
+
* @returns un groupe par raison distincte, dans l'ordre de première apparition
|
|
72
|
+
*/
|
|
73
|
+
export declare function groupSkippedChecks(skipped: ReturnType<typeof skippedChecks>): ISkippedCheckGroup[];
|
|
74
|
+
/**
|
|
75
|
+
* Taille le rapport de diagnostic pour un AGENT : les mêmes faits, sans redite.
|
|
76
|
+
*
|
|
77
|
+
* Le `--json` de `nodefony doctor` reste complet ; seule la porte MCP taille,
|
|
78
|
+
* parce que ce qu'elle rend se relit à chaque tour suivant de l'agent. Trois
|
|
79
|
+
* coupes : `execution` (que `skipped` résume déjà), les raisons de `skipped`
|
|
80
|
+
* regroupées ({@link groupSkippedChecks}), les liens `open` des derniers
|
|
81
|
+
* démarrages (faits pour un humain qui clique).
|
|
82
|
+
*
|
|
83
|
+
* @param report - le rapport de `collectDoctorReport`
|
|
84
|
+
* @returns le verdict, son compte, puis le rapport sans redite
|
|
85
|
+
*/
|
|
86
|
+
export declare function compactDoctorReport(report: IDoctorReport): Record<string, unknown>;
|
|
87
|
+
/**
|
|
88
|
+
* Catalogue intégré du framework, indexé par clé d'allowlist.
|
|
89
|
+
*
|
|
90
|
+
* Chaque handler capture ses dépendances par fermeture : c'est ce qui permet à
|
|
91
|
+
* ces outils d'être des {@link IMcpTool} ordinaires, du même type que
|
|
92
|
+
* ceux d'une application — le serveur n'a plus aucun cas particulier à traiter.
|
|
93
|
+
*
|
|
94
|
+
* @param deps - briques qui répondent réellement
|
|
95
|
+
*/
|
|
96
|
+
export declare function builtinMcpTools(deps: IMcpToolDeps): Record<BuiltinMcpToolKey, IMcpTool>;
|
|
97
|
+
/**
|
|
98
|
+
* Les outils du catalogue que l'allowlist de configuration retient.
|
|
99
|
+
*
|
|
100
|
+
* C'est la forme sous laquelle `@nodefony/devkit` les déclare (`getMcpTools()`) :
|
|
101
|
+
* des {@link IMcpTool} ordinaires, collectés par `@nodefony/ai` comme ceux de
|
|
102
|
+
* n'importe quel module — seul le préfixe `nodefony_`, réservé aux modules
|
|
103
|
+
* `@nodefony/*`, les distingue.
|
|
104
|
+
*
|
|
105
|
+
* @param allowlist - clés courtes retenues (cf {@link BUILTIN_MCP_TOOL_KEYS})
|
|
106
|
+
* @param deps - briques qui répondent réellement
|
|
107
|
+
* @returns les outils retenus, dans l'ordre de l'allowlist
|
|
108
|
+
*/
|
|
109
|
+
export declare function selectBuiltinMcpTools(allowlist: readonly string[], deps: IMcpToolDeps): IMcpTool[];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Service, Module } from "nodefony";
|
|
2
|
-
import type {
|
|
2
|
+
import type { IMcpTool, IProtectedResourceInput } from "nodefony";
|
|
3
|
+
import { type IMcpGate, type ITicketSessionGate } from "@nodefony/ai";
|
|
4
|
+
import { type IMcpToolDeps } from "../mcp/tools.js";
|
|
3
5
|
import type { IDevkitCard, IDevkitService } from "../interfaces/IDevkitService.js";
|
|
4
6
|
import { type IDevkitConfig } from "../config/config.js";
|
|
5
7
|
/**
|
|
@@ -12,7 +14,7 @@ import { type IDevkitConfig } from "../config/config.js";
|
|
|
12
14
|
*
|
|
13
15
|
* Un service porte DEUX noms, et c'est normal :
|
|
14
16
|
* `@injectable()` → nomme la CLASSE (`DevkitService`),
|
|
15
|
-
* c'est ce qu'on écrit dans `@
|
|
17
|
+
* c'est ce qu'on écrit dans `@Inject("…")`
|
|
16
18
|
* `super("devkit", …)` → nomme l'INSTANCE, sa clé dans le conteneur,
|
|
17
19
|
* c'est ce qu'on écrit dans `kernel.get("…")`
|
|
18
20
|
* Les deux mènent à la MÊME instance : le conteneur les réconcilie via la classe.
|
|
@@ -28,13 +30,13 @@ import { type IDevkitConfig } from "../config/config.js";
|
|
|
28
30
|
* ```ts
|
|
29
31
|
* // 1. INJECTION par le constructeur — la dépendance est DÉCLARÉE, donc le
|
|
30
32
|
* // conteneur l'ordonnance et elle se voit dans la signature (nom de CLASSE).
|
|
31
|
-
* import {
|
|
33
|
+
* import { Inject, injectable, Service, Module } from "nodefony";
|
|
32
34
|
*
|
|
33
35
|
* @injectable()
|
|
34
36
|
* class ReportService extends Service {
|
|
35
37
|
* constructor(
|
|
36
38
|
* module: Module,
|
|
37
|
-
* @
|
|
39
|
+
* @Inject("DevkitService") private devkit: DevkitService,
|
|
38
40
|
* ) {
|
|
39
41
|
* super("report", module.container, module.notificationsCenter);
|
|
40
42
|
* }
|
|
@@ -46,6 +48,7 @@ import { type IDevkitConfig } from "../config/config.js";
|
|
|
46
48
|
* ```
|
|
47
49
|
*/
|
|
48
50
|
declare class DevkitService extends Service implements IDevkitService {
|
|
51
|
+
#private;
|
|
49
52
|
module: Module;
|
|
50
53
|
private readonly cfg;
|
|
51
54
|
constructor(module: Module);
|
|
@@ -97,6 +100,16 @@ declare class DevkitService extends Service implements IDevkitService {
|
|
|
97
100
|
* n'est pas garanti être celui du projet).
|
|
98
101
|
*/
|
|
99
102
|
mcpToolDeps(): IMcpToolDeps;
|
|
103
|
+
/**
|
|
104
|
+
* Les outils `nodefony_*` retenus par l'allowlist `mcp.tools`.
|
|
105
|
+
*
|
|
106
|
+
* Recomposés à chaque appel, jamais mémorisés : la collecte a lieu à la
|
|
107
|
+
* requête MCP, sur une porte qui n'existe qu'en développement — un cache
|
|
108
|
+
* serait une structure de plus à invalider pour un gain nul.
|
|
109
|
+
*
|
|
110
|
+
* @returns les outils, dans l'ordre de l'allowlist
|
|
111
|
+
*/
|
|
112
|
+
mcpTools(): IMcpTool[];
|
|
100
113
|
/**
|
|
101
114
|
* Les scopes que la porte MCP EXIGE — dérivés des outils qu'elle déclare.
|
|
102
115
|
*
|
|
@@ -136,6 +149,30 @@ declare class DevkitService extends Service implements IDevkitService {
|
|
|
136
149
|
* @returns une entrée pour la porte MCP, ou aucune
|
|
137
150
|
*/
|
|
138
151
|
publishedProtectedResources(): readonly IProtectedResourceInput[];
|
|
152
|
+
/**
|
|
153
|
+
* La porte MCP de développement — définie au premier usage, une fois.
|
|
154
|
+
*
|
|
155
|
+
* Bâtie sur `defineMcpGate` comme celle de n'importe quelle application : ses
|
|
156
|
+
* réglages viennent de `devkit.mcp.*`, elle sert les outils de TOUS les modules
|
|
157
|
+
* chargés (`tools: "modules"` — l'outillage éprouve aussi ceux de l'app), et
|
|
158
|
+
* accorde le rôle d'opérateur à qui l'atteint sans jeton. Ce rôle n'est sûr que
|
|
159
|
+
* parce que son PÉRIMÈTRE la protège (module `policy: "dev"`, absent en
|
|
160
|
+
* production) ; une porte protégée par un serveur d'autorisation le tire, elle,
|
|
161
|
+
* des scopes du jeton.
|
|
162
|
+
*
|
|
163
|
+
* @returns la porte, prête à servir.
|
|
164
|
+
*/
|
|
165
|
+
mcpGate(): IMcpGate;
|
|
166
|
+
/**
|
|
167
|
+
* La porte de session du profilage — définie au premier usage, une fois.
|
|
168
|
+
*
|
|
169
|
+
* Bâtie sur `defineTicketSessionGate` comme le ferait une application pour
|
|
170
|
+
* ses propres outils : locale seulement (défaut de la porte), facteur d'audit
|
|
171
|
+
* {@link PROFILE_SESSION_FACTOR}.
|
|
172
|
+
*
|
|
173
|
+
* @returns la porte, prête à émettre et à servir.
|
|
174
|
+
*/
|
|
175
|
+
profileSessionGate(): ITicketSessionGate;
|
|
139
176
|
status(): {
|
|
140
177
|
ready: boolean;
|
|
141
178
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facteur d'authentification déclaré au flux de session : l'audit écrit
|
|
3
|
+
* `login.success` avec cette raison, ce qui distingue une session de profilage
|
|
4
|
+
* d'une vraie connexion.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PROFILE_SESSION_FACTOR = "devkit";
|
|
7
|
+
/**
|
|
8
|
+
* Chemin de la route de connexion du profilage, que l'outil appelle. Hors du
|
|
9
|
+
* motif de la zone d'administration (`^/nodefony/[^/]+/api`). Le contrôleur
|
|
10
|
+
* l'écrit en littéraux ; un test tient l'égalité.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PROFILE_SESSION_PATH = "/nodefony/devkit/profile-session";
|