@godot-mcp/control-plane 0.0.0 → 0.1.0

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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/audit/jsonlAuditSink.d.ts +33 -0
  4. package/dist/audit/jsonlAuditSink.d.ts.map +1 -0
  5. package/dist/audit/jsonlAuditSink.js +57 -0
  6. package/dist/audit/jsonlAuditSink.js.map +1 -0
  7. package/dist/audit/redact.d.ts +2 -0
  8. package/dist/audit/redact.d.ts.map +1 -0
  9. package/dist/audit/redact.js +44 -0
  10. package/dist/audit/redact.js.map +1 -0
  11. package/dist/auth/pairingDescriptor.d.ts +44 -0
  12. package/dist/auth/pairingDescriptor.d.ts.map +1 -0
  13. package/dist/auth/pairingDescriptor.js +91 -0
  14. package/dist/auth/pairingDescriptor.js.map +1 -0
  15. package/dist/auth/runtimeDirectory.d.ts +3 -0
  16. package/dist/auth/runtimeDirectory.d.ts.map +1 -0
  17. package/dist/auth/runtimeDirectory.js +30 -0
  18. package/dist/auth/runtimeDirectory.js.map +1 -0
  19. package/dist/auth/sessionCrypto.d.ts +18 -0
  20. package/dist/auth/sessionCrypto.d.ts.map +1 -0
  21. package/dist/auth/sessionCrypto.js +118 -0
  22. package/dist/auth/sessionCrypto.js.map +1 -0
  23. package/dist/editor/editorMutationService.d.ts +21 -0
  24. package/dist/editor/editorMutationService.d.ts.map +1 -0
  25. package/dist/editor/editorMutationService.js +120 -0
  26. package/dist/editor/editorMutationService.js.map +1 -0
  27. package/dist/editor/mutationLedger.d.ts +30 -0
  28. package/dist/editor/mutationLedger.d.ts.map +1 -0
  29. package/dist/editor/mutationLedger.js +133 -0
  30. package/dist/editor/mutationLedger.js.map +1 -0
  31. package/dist/errors.d.ts +12 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +23 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/evidence/evidenceStore.d.ts +63 -0
  36. package/dist/evidence/evidenceStore.d.ts.map +1 -0
  37. package/dist/evidence/evidenceStore.js +350 -0
  38. package/dist/evidence/evidenceStore.js.map +1 -0
  39. package/dist/extensions/extensionRegistry.d.ts +33 -0
  40. package/dist/extensions/extensionRegistry.d.ts.map +1 -0
  41. package/dist/extensions/extensionRegistry.js +37 -0
  42. package/dist/extensions/extensionRegistry.js.map +1 -0
  43. package/dist/help/coreHelp.d.ts +10 -0
  44. package/dist/help/coreHelp.d.ts.map +1 -0
  45. package/dist/help/coreHelp.js +82 -0
  46. package/dist/help/coreHelp.js.map +1 -0
  47. package/dist/index.d.ts +37 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/policy/authorize.d.ts +5 -0
  52. package/dist/policy/authorize.d.ts.map +1 -0
  53. package/dist/policy/authorize.js +19 -0
  54. package/dist/policy/authorize.js.map +1 -0
  55. package/dist/policy/capabilities.d.ts +36 -0
  56. package/dist/policy/capabilities.d.ts.map +1 -0
  57. package/dist/policy/capabilities.js +129 -0
  58. package/dist/policy/capabilities.js.map +1 -0
  59. package/dist/project/artifactStore.d.ts +32 -0
  60. package/dist/project/artifactStore.d.ts.map +1 -0
  61. package/dist/project/artifactStore.js +172 -0
  62. package/dist/project/artifactStore.js.map +1 -0
  63. package/dist/project/pathPolicy.d.ts +4 -0
  64. package/dist/project/pathPolicy.d.ts.map +1 -0
  65. package/dist/project/pathPolicy.js +74 -0
  66. package/dist/project/pathPolicy.js.map +1 -0
  67. package/dist/project/projectConfig.d.ts +10 -0
  68. package/dist/project/projectConfig.d.ts.map +1 -0
  69. package/dist/project/projectConfig.js +63 -0
  70. package/dist/project/projectConfig.js.map +1 -0
  71. package/dist/project/projectIdentity.d.ts +8 -0
  72. package/dist/project/projectIdentity.d.ts.map +1 -0
  73. package/dist/project/projectIdentity.js +58 -0
  74. package/dist/project/projectIdentity.js.map +1 -0
  75. package/dist/project/projectJobJournal.d.ts +49 -0
  76. package/dist/project/projectJobJournal.d.ts.map +1 -0
  77. package/dist/project/projectJobJournal.js +67 -0
  78. package/dist/project/projectJobJournal.js.map +1 -0
  79. package/dist/project/projectJobService.d.ts +52 -0
  80. package/dist/project/projectJobService.d.ts.map +1 -0
  81. package/dist/project/projectJobService.js +289 -0
  82. package/dist/project/projectJobService.js.map +1 -0
  83. package/dist/project/projectMutationService.d.ts +40 -0
  84. package/dist/project/projectMutationService.d.ts.map +1 -0
  85. package/dist/project/projectMutationService.js +145 -0
  86. package/dist/project/projectMutationService.js.map +1 -0
  87. package/dist/project/projectPreflight.d.ts +7 -0
  88. package/dist/project/projectPreflight.d.ts.map +1 -0
  89. package/dist/project/projectPreflight.js +50 -0
  90. package/dist/project/projectPreflight.js.map +1 -0
  91. package/dist/project/projectProcess.d.ts +40 -0
  92. package/dist/project/projectProcess.d.ts.map +1 -0
  93. package/dist/project/projectProcess.js +196 -0
  94. package/dist/project/projectProcess.js.map +1 -0
  95. package/dist/project/projectService.d.ts +20 -0
  96. package/dist/project/projectService.d.ts.map +1 -0
  97. package/dist/project/projectService.js +35 -0
  98. package/dist/project/projectService.js.map +1 -0
  99. package/dist/project/secureJournalFile.d.ts +3 -0
  100. package/dist/project/secureJournalFile.d.ts.map +1 -0
  101. package/dist/project/secureJournalFile.js +56 -0
  102. package/dist/project/secureJournalFile.js.map +1 -0
  103. package/dist/runtime/debugTokenStore.d.ts +41 -0
  104. package/dist/runtime/debugTokenStore.d.ts.map +1 -0
  105. package/dist/runtime/debugTokenStore.js +105 -0
  106. package/dist/runtime/debugTokenStore.js.map +1 -0
  107. package/dist/runtime/debuggerClient.d.ts +14 -0
  108. package/dist/runtime/debuggerClient.d.ts.map +1 -0
  109. package/dist/runtime/debuggerClient.js +21 -0
  110. package/dist/runtime/debuggerClient.js.map +1 -0
  111. package/dist/runtime/inputReceipt.d.ts +15 -0
  112. package/dist/runtime/inputReceipt.d.ts.map +1 -0
  113. package/dist/runtime/inputReceipt.js +36 -0
  114. package/dist/runtime/inputReceipt.js.map +1 -0
  115. package/dist/runtime/runtimeDescriptor.d.ts +50 -0
  116. package/dist/runtime/runtimeDescriptor.d.ts.map +1 -0
  117. package/dist/runtime/runtimeDescriptor.js +175 -0
  118. package/dist/runtime/runtimeDescriptor.js.map +1 -0
  119. package/dist/runtime/runtimeProcess.d.ts +39 -0
  120. package/dist/runtime/runtimeProcess.d.ts.map +1 -0
  121. package/dist/runtime/runtimeProcess.js +180 -0
  122. package/dist/runtime/runtimeProcess.js.map +1 -0
  123. package/dist/runtime/runtimeService.d.ts +130 -0
  124. package/dist/runtime/runtimeService.d.ts.map +1 -0
  125. package/dist/runtime/runtimeService.js +919 -0
  126. package/dist/runtime/runtimeService.js.map +1 -0
  127. package/dist/session/sessionService.d.ts +52 -0
  128. package/dist/session/sessionService.d.ts.map +1 -0
  129. package/dist/session/sessionService.js +72 -0
  130. package/dist/session/sessionService.js.map +1 -0
  131. package/dist/unsafe/unsafeFixtureAuthority.d.ts +27 -0
  132. package/dist/unsafe/unsafeFixtureAuthority.d.ts.map +1 -0
  133. package/dist/unsafe/unsafeFixtureAuthority.js +130 -0
  134. package/dist/unsafe/unsafeFixtureAuthority.js.map +1 -0
  135. package/dist/unsafe/unsafeFixtureProcess.d.ts +30 -0
  136. package/dist/unsafe/unsafeFixtureProcess.d.ts.map +1 -0
  137. package/dist/unsafe/unsafeFixtureProcess.js +119 -0
  138. package/dist/unsafe/unsafeFixtureProcess.js.map +1 -0
  139. package/dist/unsafe/unsafeFixtureService.d.ts +41 -0
  140. package/dist/unsafe/unsafeFixtureService.d.ts.map +1 -0
  141. package/dist/unsafe/unsafeFixtureService.js +162 -0
  142. package/dist/unsafe/unsafeFixtureService.js.map +1 -0
  143. package/dist/visual/pngComparison.d.ts +12 -0
  144. package/dist/visual/pngComparison.d.ts.map +1 -0
  145. package/dist/visual/pngComparison.js +136 -0
  146. package/dist/visual/pngComparison.js.map +1 -0
  147. package/dist/visual/scenarioService.d.ts +50 -0
  148. package/dist/visual/scenarioService.d.ts.map +1 -0
  149. package/dist/visual/scenarioService.js +421 -0
  150. package/dist/visual/scenarioService.js.map +1 -0
  151. package/dist/visual/visualService.d.ts +27 -0
  152. package/dist/visual/visualService.d.ts.map +1 -0
  153. package/dist/visual/visualService.js +70 -0
  154. package/dist/visual/visualService.js.map +1 -0
  155. package/package.json +26 -6
  156. package/index.js +0 -1
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ export { GodotMcpException } from "./errors.js";
2
+ export { ExtensionRegistry } from "./extensions/extensionRegistry.js";
3
+ export { UNSAFE_CONFIRMATION_PHRASE, approveUnsafeFixtureCopy, consumeUnsafeFixtureActivation, registerUnsafeFixture, stampUnsafeFixtureCopy, } from "./unsafe/unsafeFixtureAuthority.js";
4
+ export { UnsafeFixtureProcess } from "./unsafe/unsafeFixtureProcess.js";
5
+ export { UnsafeFixtureService } from "./unsafe/unsafeFixtureService.js";
6
+ export { EditorMutationService, editorMutationRequestDigest, } from "./editor/editorMutationService.js";
7
+ export { MutationLedger, } from "./editor/mutationLedger.js";
8
+ export { ProjectConfigSchema, createProjectConfig, } from "./project/projectConfig.js";
9
+ export { discoverProject, readProjectIdentity, } from "./project/projectIdentity.js";
10
+ export { resolveProjectPath } from "./project/pathPolicy.js";
11
+ export { ArtifactStore, scanArtifactDirectory, } from "./project/artifactStore.js";
12
+ export { OwnedProjectProcess, projectProcessFingerprint, projectGodotArguments, recoverOwnedProjectProcess, scrubProjectEnvironment, } from "./project/projectProcess.js";
13
+ export { ProjectJobService, } from "./project/projectJobService.js";
14
+ export { ProjectJobJournal, } from "./project/projectJobJournal.js";
15
+ export { ProjectMutationJournal, ProjectMutationService, } from "./project/projectMutationService.js";
16
+ export { ProjectService } from "./project/projectService.js";
17
+ export { assertBuildSolutionsPreflight, assertExportPreflight, projectOperationPreflight, } from "./project/projectPreflight.js";
18
+ export { CORE_CAPABILITIES_POLICY, CORE_CAPTURE_POLICY, CORE_DOCTOR_POLICY, CORE_HELP_POLICY, CORE_POLICIES, CORE_QUERY_POLICY, CORE_SESSION_POLICY, EDITOR_POLICIES, EDITOR_POLICY, INPUT_POLICIES, INPUT_POLICY, PROJECT_POLICIES, PROJECT_POLICY, UNSAFE_POLICIES, UNSAFE_POLICY, PHASE_ONE_POLICIES, RUNTIME_CAPTURE_POLICY, RUNTIME_POLICIES, RUNTIME_POLICY, VISUAL_POLICIES, VISUAL_POLICY, expandPermissionTiers, visibleCapabilities, } from "./policy/capabilities.js";
19
+ export { authorize } from "./policy/authorize.js";
20
+ export { redactAuditValue } from "./audit/redact.js";
21
+ export { EvidenceStore, } from "./evidence/evidenceStore.js";
22
+ export { JsonlAuditSink, } from "./audit/jsonlAuditSink.js";
23
+ export { ensureRuntimeDirectory, runtimeDirectoryPath } from "./auth/runtimeDirectory.js";
24
+ export { PairingDescriptorSchema, consumePairingDescriptor, createPairingDescriptor, } from "./auth/pairingDescriptor.js";
25
+ export { EnvelopeVerifier, deriveSessionKey, envelopeSigningText, signEnvelope, verifyEnvelope, } from "./auth/sessionCrypto.js";
26
+ export { getCoreHelp, } from "./help/coreHelp.js";
27
+ export { SessionService, } from "./session/sessionService.js";
28
+ export { RuntimeDescriptorSchema, consumeRuntimeDescriptor, createRuntimeDescriptor, } from "./runtime/runtimeDescriptor.js";
29
+ export { AUTHENTICATED_DEBUGGER_COMMANDS, DebuggerClientError, } from "./runtime/debuggerClient.js";
30
+ export { DebugTokenStore, DebugTokenStoreError, } from "./runtime/debugTokenStore.js";
31
+ export { assertLoopbackListenerOwnedByProcess, assertLoopbackListenersOwnedByProcess, listenerPortsAreDistinct, OwnedGodotProcess, godotRuntimeArguments, scrubRuntimeEnvironment, } from "./runtime/runtimeProcess.js";
32
+ export { RuntimeService, } from "./runtime/runtimeService.js";
33
+ export { inputTraceEvents, summarizeInputForAudit, traceSha256, } from "./runtime/inputReceipt.js";
34
+ export { comparePng } from "./visual/pngComparison.js";
35
+ export { ScenarioService, } from "./visual/scenarioService.js";
36
+ export { VisualService, } from "./visual/visualService.js";
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type CommandPolicy, type SessionGrants } from "./capabilities.js";
2
+ export declare function authorize(grants: SessionGrants, policy: CommandPolicy): {
3
+ allowed: true;
4
+ };
5
+ //# sourceMappingURL=authorize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/policy/authorize.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyB,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElG,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAczF"}
@@ -0,0 +1,19 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { GodotMcpException } from "../errors.js";
3
+ import { expandPermissionTiers } from "./capabilities.js";
4
+ export function authorize(grants, policy) {
5
+ const tiers = expandPermissionTiers(grants.tiers);
6
+ const requiredPacks = policy.requiredPacks ?? [policy.pack];
7
+ if (!tiers.includes(policy.tier) || !requiredPacks.every((pack) => grants.packs.includes(pack))) {
8
+ throw new GodotMcpException({
9
+ code: "PERMISSION_REQUIRED",
10
+ message: `${policy.command} requires tier ${policy.tier} and capability packs ${requiredPacks.join(", ")}`,
11
+ retryable: false,
12
+ correlationId: randomUUID(),
13
+ partialEffects: false,
14
+ rollback: "not_needed",
15
+ });
16
+ }
17
+ return { allowed: true };
18
+ }
19
+ //# sourceMappingURL=authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/policy/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAA0C,MAAM,mBAAmB,CAAC;AAElG,MAAM,UAAU,SAAS,CAAC,MAAqB,EAAE,MAAqB;IACpE,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,IAAI,iBAAiB,CAAC;YAC1B,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,kBAAkB,MAAM,CAAC,IAAI,yBAAyB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC1G,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,UAAU,EAAE;YAC3B,cAAc,EAAE,KAAK;YACrB,QAAQ,EAAE,YAAY;SACvB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { CapabilityPack, PermissionTier } from "@godot-mcp/protocol";
2
+ export interface SessionGrants {
3
+ tiers: PermissionTier[];
4
+ packs: CapabilityPack[];
5
+ }
6
+ export interface CommandPolicy {
7
+ command: string;
8
+ tier: PermissionTier;
9
+ pack: CapabilityPack;
10
+ requiredPacks?: readonly CapabilityPack[];
11
+ mutating: boolean;
12
+ }
13
+ export declare function expandPermissionTiers(tiers: readonly PermissionTier[]): PermissionTier[];
14
+ export declare const CORE_CAPABILITIES_POLICY: CommandPolicy;
15
+ export declare const CORE_DOCTOR_POLICY: CommandPolicy;
16
+ export declare const CORE_HELP_POLICY: CommandPolicy;
17
+ export declare const CORE_SESSION_POLICY: CommandPolicy;
18
+ export declare const CORE_QUERY_POLICY: CommandPolicy;
19
+ export declare const CORE_CAPTURE_POLICY: CommandPolicy;
20
+ export declare const RUNTIME_POLICY: CommandPolicy;
21
+ export declare const RUNTIME_CAPTURE_POLICY: CommandPolicy;
22
+ export declare const INPUT_POLICY: CommandPolicy;
23
+ export declare const EDITOR_POLICY: CommandPolicy;
24
+ export declare const VISUAL_POLICY: CommandPolicy;
25
+ export declare const PROJECT_POLICY: CommandPolicy;
26
+ export declare const UNSAFE_POLICY: CommandPolicy;
27
+ export declare const PHASE_ONE_POLICIES: readonly CommandPolicy[];
28
+ export declare const CORE_POLICIES: readonly CommandPolicy[];
29
+ export declare const RUNTIME_POLICIES: readonly CommandPolicy[];
30
+ export declare const INPUT_POLICIES: readonly CommandPolicy[];
31
+ export declare const EDITOR_POLICIES: readonly CommandPolicy[];
32
+ export declare const VISUAL_POLICIES: readonly CommandPolicy[];
33
+ export declare const PROJECT_POLICIES: readonly CommandPolicy[];
34
+ export declare const UNSAFE_POLICIES: readonly CommandPolicy[];
35
+ export declare function visibleCapabilities(grants: SessionGrants): CommandPolicy[];
36
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/policy/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C,QAAQ,EAAE,OAAO,CAAC;CACnB;AAkBD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,cAAc,EAAE,CAMxF;AAED,eAAO,MAAM,wBAAwB,EAAE,aAKtC,CAAC;AACF,eAAO,MAAM,kBAAkB,EAAE,aAKhC,CAAC;AACF,eAAO,MAAM,gBAAgB,EAAE,aAK9B,CAAC;AACF,eAAO,MAAM,mBAAmB,EAAE,aAKjC,CAAC;AACF,eAAO,MAAM,iBAAiB,EAAE,aAK/B,CAAC;AACF,eAAO,MAAM,mBAAmB,EAAE,aAKjC,CAAC;AACF,eAAO,MAAM,cAAc,EAAE,aAK5B,CAAC;AACF,eAAO,MAAM,sBAAsB,EAAE,aAKpC,CAAC;AACF,eAAO,MAAM,YAAY,EAAE,aAK1B,CAAC;AACF,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC;AACF,eAAO,MAAM,aAAa,EAAE,aAM3B,CAAC;AACF,eAAO,MAAM,cAAc,EAAE,aAK5B,CAAC;AACF,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,aAAa,EAKtD,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EAOjD,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAGpD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAAmB,CAAC;AACvE,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAAoB,CAAC;AACzE,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAAoB,CAAC;AACzE,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAqB,CAAC;AAC3E,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAAoB,CAAC;AAEzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAK1E"}
@@ -0,0 +1,129 @@
1
+ const TIER_EXPANSION = {
2
+ observe: ["observe"],
3
+ runtime_control: ["observe", "runtime_control"],
4
+ project_mutate: ["observe", "runtime_control", "project_mutate"],
5
+ project_operate: ["observe", "runtime_control", "project_mutate", "project_operate"],
6
+ unsafe_fixture: ["observe", "unsafe_fixture"],
7
+ };
8
+ const TIER_ORDER = [
9
+ "observe",
10
+ "runtime_control",
11
+ "project_mutate",
12
+ "project_operate",
13
+ "unsafe_fixture",
14
+ ];
15
+ export function expandPermissionTiers(tiers) {
16
+ const expanded = new Set();
17
+ for (const tier of tiers) {
18
+ for (const implied of TIER_EXPANSION[tier])
19
+ expanded.add(implied);
20
+ }
21
+ return TIER_ORDER.filter((tier) => expanded.has(tier));
22
+ }
23
+ export const CORE_CAPABILITIES_POLICY = {
24
+ command: "godot_capabilities",
25
+ tier: "observe",
26
+ pack: "core",
27
+ mutating: false,
28
+ };
29
+ export const CORE_DOCTOR_POLICY = {
30
+ command: "godot_doctor",
31
+ tier: "observe",
32
+ pack: "core",
33
+ mutating: false,
34
+ };
35
+ export const CORE_HELP_POLICY = {
36
+ command: "godot_help",
37
+ tier: "observe",
38
+ pack: "core",
39
+ mutating: false,
40
+ };
41
+ export const CORE_SESSION_POLICY = {
42
+ command: "godot_session",
43
+ tier: "observe",
44
+ pack: "core",
45
+ mutating: false,
46
+ };
47
+ export const CORE_QUERY_POLICY = {
48
+ command: "godot_query",
49
+ tier: "observe",
50
+ pack: "core",
51
+ mutating: false,
52
+ };
53
+ export const CORE_CAPTURE_POLICY = {
54
+ command: "godot_capture",
55
+ tier: "observe",
56
+ pack: "core",
57
+ mutating: false,
58
+ };
59
+ export const RUNTIME_POLICY = {
60
+ command: "godot_runtime",
61
+ tier: "runtime_control",
62
+ pack: "runtime",
63
+ mutating: true,
64
+ };
65
+ export const RUNTIME_CAPTURE_POLICY = {
66
+ command: "godot_runtime_capture",
67
+ tier: "runtime_control",
68
+ pack: "runtime",
69
+ mutating: true,
70
+ };
71
+ export const INPUT_POLICY = {
72
+ command: "godot_input",
73
+ tier: "runtime_control",
74
+ pack: "input",
75
+ mutating: true,
76
+ };
77
+ export const EDITOR_POLICY = {
78
+ command: "godot_editor",
79
+ tier: "project_mutate",
80
+ pack: "editor",
81
+ mutating: true,
82
+ };
83
+ export const VISUAL_POLICY = {
84
+ command: "godot_visual",
85
+ tier: "runtime_control",
86
+ pack: "visual",
87
+ requiredPacks: ["runtime", "input", "visual"],
88
+ mutating: true,
89
+ };
90
+ export const PROJECT_POLICY = {
91
+ command: "godot_project",
92
+ tier: "project_operate",
93
+ pack: "project",
94
+ mutating: true,
95
+ };
96
+ export const UNSAFE_POLICY = {
97
+ command: "godot_unsafe_fixture",
98
+ tier: "unsafe_fixture",
99
+ pack: "unsafe",
100
+ mutating: true,
101
+ };
102
+ export const PHASE_ONE_POLICIES = [
103
+ CORE_CAPABILITIES_POLICY,
104
+ CORE_DOCTOR_POLICY,
105
+ CORE_HELP_POLICY,
106
+ CORE_SESSION_POLICY,
107
+ ];
108
+ export const CORE_POLICIES = [
109
+ CORE_CAPABILITIES_POLICY,
110
+ CORE_CAPTURE_POLICY,
111
+ CORE_DOCTOR_POLICY,
112
+ CORE_HELP_POLICY,
113
+ CORE_QUERY_POLICY,
114
+ CORE_SESSION_POLICY,
115
+ ];
116
+ export const RUNTIME_POLICIES = [
117
+ RUNTIME_CAPTURE_POLICY,
118
+ RUNTIME_POLICY,
119
+ ];
120
+ export const INPUT_POLICIES = [INPUT_POLICY];
121
+ export const EDITOR_POLICIES = [EDITOR_POLICY];
122
+ export const VISUAL_POLICIES = [VISUAL_POLICY];
123
+ export const PROJECT_POLICIES = [PROJECT_POLICY];
124
+ export const UNSAFE_POLICIES = [UNSAFE_POLICY];
125
+ export function visibleCapabilities(grants) {
126
+ const tiers = expandPermissionTiers(grants.tiers);
127
+ return [...CORE_POLICIES, ...RUNTIME_POLICIES, ...INPUT_POLICIES, ...EDITOR_POLICIES, ...VISUAL_POLICIES, ...PROJECT_POLICIES, ...UNSAFE_POLICIES].filter((policy) => tiers.includes(policy.tier) && (policy.requiredPacks ?? [policy.pack]).every((pack) => grants.packs.includes(pack)));
128
+ }
129
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/policy/capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type ProjectArtifactManifest } from "@godot-mcp/protocol";
2
+ export interface ArtifactScanFinding {
3
+ relativePath: string;
4
+ marker: string;
5
+ }
6
+ export interface ArtifactScanEntry {
7
+ relativePath: string;
8
+ byteLength: number;
9
+ sha256: string;
10
+ }
11
+ export interface ArtifactScanResult {
12
+ leakFree: boolean;
13
+ findings: ArtifactScanFinding[];
14
+ entries: ArtifactScanEntry[];
15
+ byteLength: number;
16
+ sha256: string;
17
+ }
18
+ export interface ArtifactScanOptions {
19
+ maxEntries?: number;
20
+ maxBytes?: number;
21
+ chunkBytes?: number;
22
+ }
23
+ export declare function scanArtifactDirectory(directory: string, options?: ArtifactScanOptions): Promise<ArtifactScanResult>;
24
+ export declare class ArtifactStore {
25
+ private readonly projectRoot;
26
+ constructor(projectRoot: string);
27
+ allocate(jobToken: string, artifactName: string): Promise<{
28
+ path: string;
29
+ }>;
30
+ finalize(jobToken: string, artifactName: string): Promise<ProjectArtifactManifest>;
31
+ }
32
+ //# sourceMappingURL=artifactStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifactStore.d.ts","sourceRoot":"","sources":["../../src/project/artifactStore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgD,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AA+DjH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkE7H;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,MAAM;IAE1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAW3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAezF"}
@@ -0,0 +1,172 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { lstat, mkdir, readdir } from "node:fs/promises";
4
+ import { join, relative, resolve, sep } from "node:path";
5
+ import { canonicalJson, ProjectArtifactManifestSchema } from "@godot-mcp/protocol";
6
+ import { GodotMcpException } from "../errors.js";
7
+ const JOB_TOKEN_PATTERN = /^pjob_[A-Za-z0-9_-]{43}$/;
8
+ const ARTIFACT_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
9
+ const DEFAULT_MAX_ENTRIES = 10_000;
10
+ const DEFAULT_MAX_BYTES = 4 * 1024 * 1024 * 1024;
11
+ const DEFAULT_CHUNK_BYTES = 64 * 1024;
12
+ const LEAK_MARKERS = [
13
+ "addons/godot_mcp",
14
+ "godot_mcp/runtime",
15
+ "godot-mcp://",
16
+ "runtime_harness.gd",
17
+ "godot_mcp_unsafe",
18
+ "godotmcpruntimeharness",
19
+ "godotmcpbridgeclient",
20
+ "godotmcpprojectoperations",
21
+ "godot_mcp_runtime:hello",
22
+ ".godot-mcp-unsafe-fixture",
23
+ ];
24
+ function artifactError(code, message) {
25
+ return new GodotMcpException({
26
+ code,
27
+ message,
28
+ retryable: false,
29
+ correlationId: randomUUID(),
30
+ partialEffects: code === "EXPORT_LEAK_DETECTED",
31
+ rollback: "not_needed",
32
+ });
33
+ }
34
+ function validateIdentity(jobToken, artifactName) {
35
+ if (!JOB_TOKEN_PATTERN.test(jobToken) || (artifactName !== undefined && !ARTIFACT_NAME_PATTERN.test(artifactName))) {
36
+ throw artifactError("PATH_DENIED", "Artifact identity is invalid");
37
+ }
38
+ }
39
+ async function ensurePlainDirectory(root, segments, create) {
40
+ let current = root;
41
+ const rootMetadata = await lstat(current).catch(() => undefined);
42
+ if (!rootMetadata || rootMetadata.isSymbolicLink() || !rootMetadata.isDirectory()) {
43
+ throw artifactError("PATH_DENIED", "Artifact root must be a regular non-symlink directory");
44
+ }
45
+ for (const segment of segments) {
46
+ current = join(current, segment);
47
+ let metadata = await lstat(current).catch(() => undefined);
48
+ if (!metadata && create) {
49
+ await mkdir(current, { mode: 0o700 }).catch(async (error) => {
50
+ if (!(await lstat(current).catch(() => undefined)))
51
+ throw error;
52
+ });
53
+ metadata = await lstat(current).catch(() => undefined);
54
+ }
55
+ if (!metadata)
56
+ throw artifactError("PRECONDITION_FAILED", "Artifact directory is unavailable");
57
+ if (metadata.isSymbolicLink() || !metadata.isDirectory())
58
+ throw artifactError("PATH_DENIED", "Artifact directories must not be symbolic links");
59
+ }
60
+ return current;
61
+ }
62
+ export async function scanArtifactDirectory(directory, options = {}) {
63
+ const root = resolve(directory);
64
+ const rootMetadata = await lstat(root).catch(() => undefined);
65
+ if (!rootMetadata || rootMetadata.isSymbolicLink() || !rootMetadata.isDirectory()) {
66
+ throw artifactError("PATH_DENIED", "Artifact scan root must be a regular non-symlink directory");
67
+ }
68
+ const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
69
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
70
+ const chunkBytes = options.chunkBytes ?? DEFAULT_CHUNK_BYTES;
71
+ if (!Number.isInteger(maxEntries) || maxEntries < 1 || maxEntries > DEFAULT_MAX_ENTRIES)
72
+ throw artifactError("PAYLOAD_TOO_LARGE", "Artifact entry limit is invalid");
73
+ if (!Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > DEFAULT_MAX_BYTES)
74
+ throw artifactError("PAYLOAD_TOO_LARGE", "Artifact byte limit is invalid");
75
+ if (!Number.isInteger(chunkBytes) || chunkBytes < 1 || chunkBytes > DEFAULT_CHUNK_BYTES)
76
+ throw artifactError("PAYLOAD_TOO_LARGE", "Artifact scan chunk is invalid");
77
+ const paths = [];
78
+ async function visit(current) {
79
+ const entries = await readdir(current, { withFileTypes: true });
80
+ entries.sort((left, right) => left.name.localeCompare(right.name));
81
+ for (const entry of entries) {
82
+ const path = join(current, entry.name);
83
+ const metadata = await lstat(path);
84
+ if (metadata.isSymbolicLink())
85
+ throw artifactError("PATH_DENIED", "Artifact trees may not contain symbolic links");
86
+ if (metadata.isDirectory()) {
87
+ await visit(path);
88
+ }
89
+ else if (metadata.isFile()) {
90
+ paths.push(path);
91
+ if (paths.length > maxEntries)
92
+ throw artifactError("PAYLOAD_TOO_LARGE", "Artifact contains too many files");
93
+ }
94
+ else {
95
+ throw artifactError("PATH_DENIED", "Artifact trees may contain only regular files and directories");
96
+ }
97
+ }
98
+ }
99
+ await visit(root);
100
+ if (paths.length === 0)
101
+ throw artifactError("PRECONDITION_FAILED", "Artifact directory is empty");
102
+ const findings = [];
103
+ const entries = [];
104
+ let totalBytes = 0;
105
+ const longestMarker = Math.max(...LEAK_MARKERS.map((marker) => marker.length));
106
+ for (const path of paths.sort()) {
107
+ const relativePath = relative(root, path).split(sep).join("/");
108
+ if (relativePath.startsWith("../") || relativePath === "..")
109
+ throw artifactError("PATH_DENIED", "Artifact path escaped its owned root");
110
+ const pathLower = relativePath.toLowerCase();
111
+ for (const marker of LEAK_MARKERS) {
112
+ if (pathLower.includes(marker) && findings.length < 64)
113
+ findings.push({ relativePath, marker });
114
+ }
115
+ const hash = createHash("sha256");
116
+ let byteLength = 0;
117
+ let tail = "";
118
+ for await (const rawChunk of createReadStream(path, { highWaterMark: chunkBytes })) {
119
+ const chunk = rawChunk;
120
+ hash.update(chunk);
121
+ byteLength += chunk.byteLength;
122
+ totalBytes += chunk.byteLength;
123
+ if (totalBytes > maxBytes)
124
+ throw artifactError("PAYLOAD_TOO_LARGE", "Artifact exceeds the scan byte limit");
125
+ const text = `${tail}${chunk.toString("latin1").toLowerCase()}`;
126
+ for (const marker of LEAK_MARKERS) {
127
+ if (text.includes(marker) && findings.length < 64 && !findings.some((finding) => finding.relativePath === relativePath && finding.marker === marker)) {
128
+ findings.push({ relativePath, marker });
129
+ }
130
+ }
131
+ tail = text.slice(-(longestMarker - 1));
132
+ }
133
+ entries.push({ relativePath, byteLength, sha256: hash.digest("hex") });
134
+ }
135
+ const sha256 = createHash("sha256").update(canonicalJson(entries)).digest("hex");
136
+ return { leakFree: findings.length === 0, findings, entries, byteLength: totalBytes, sha256 };
137
+ }
138
+ export class ArtifactStore {
139
+ projectRoot;
140
+ constructor(projectRoot) {
141
+ this.projectRoot = projectRoot;
142
+ }
143
+ async allocate(jobToken, artifactName) {
144
+ validateIdentity(jobToken, artifactName);
145
+ const parent = await ensurePlainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "artifacts"], true);
146
+ const path = join(parent, jobToken);
147
+ if (await lstat(path).catch(() => undefined))
148
+ throw artifactError("CONFLICT", "Artifact job directory already exists");
149
+ await mkdir(path, { mode: 0o700 });
150
+ const metadata = await lstat(path);
151
+ if (metadata.isSymbolicLink() || !metadata.isDirectory())
152
+ throw artifactError("PATH_DENIED", "Artifact job directory is invalid");
153
+ return { path };
154
+ }
155
+ async finalize(jobToken, artifactName) {
156
+ validateIdentity(jobToken, artifactName);
157
+ const path = await ensurePlainDirectory(this.projectRoot, [".godot", "evidence", "godot-mcp", "artifacts", jobToken], false);
158
+ const scan = await scanArtifactDirectory(path);
159
+ if (!scan.leakFree)
160
+ throw artifactError("EXPORT_LEAK_DETECTED", "Export artifact contains Godot MCP components");
161
+ const sha256 = createHash("sha256").update(canonicalJson({ name: artifactName, entries: scan.entries })).digest("hex");
162
+ return ProjectArtifactManifestSchema.parse({
163
+ uri: `godot-mcp://artifact/${jobToken}/${sha256}`,
164
+ name: artifactName,
165
+ byteLength: scan.byteLength,
166
+ sha256,
167
+ entryCount: scan.entries.length,
168
+ leakFree: true,
169
+ });
170
+ }
171
+ }
172
+ //# sourceMappingURL=artifactStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifactStore.js","sourceRoot":"","sources":["../../src/project/artifactStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ProjectIdentity } from "@godot-mcp/protocol";
2
+ export type ProjectPathMode = "read" | "write";
3
+ export declare function resolveProjectPath(identity: ProjectIdentity, resPath: string, mode: ProjectPathMode): Promise<string>;
4
+ //# sourceMappingURL=pathPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathPolicy.d.ts","sourceRoot":"","sources":["../../src/project/pathPolicy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAI3D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAsC/C,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
@@ -0,0 +1,74 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { realpath } from "node:fs/promises";
3
+ import { dirname, isAbsolute, relative as relativePath, resolve, sep } from "node:path";
4
+ import { GodotMcpException } from "../errors.js";
5
+ const CREDENTIAL_FILENAME = /(?:credential|secret|token|api[-_.]?key|private[-_.]?key|id_rsa)/i;
6
+ function pathDenied(resourcePath) {
7
+ return new GodotMcpException({
8
+ code: "PATH_DENIED",
9
+ message: `Project path is denied: ${resourcePath}`,
10
+ retryable: false,
11
+ correlationId: randomUUID(),
12
+ partialEffects: false,
13
+ rollback: "not_needed",
14
+ });
15
+ }
16
+ function isContained(root, target) {
17
+ const relative = relativePath(root, target);
18
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${sep}`) && !isAbsolute(relative));
19
+ }
20
+ async function nearestExistingRealParent(candidate, root) {
21
+ let current = candidate;
22
+ while (isContained(root, current)) {
23
+ try {
24
+ return await realpath(current);
25
+ }
26
+ catch (error) {
27
+ if (error.code !== "ENOENT") {
28
+ throw error;
29
+ }
30
+ }
31
+ if (current === root) {
32
+ break;
33
+ }
34
+ current = dirname(current);
35
+ }
36
+ throw pathDenied(candidate);
37
+ }
38
+ export async function resolveProjectPath(identity, resPath, mode) {
39
+ if (!resPath.startsWith("res://") || resPath.includes("\0")) {
40
+ throw pathDenied(resPath);
41
+ }
42
+ const relative = resPath.slice("res://".length);
43
+ const parts = relative.split("/");
44
+ if (relative.length === 0 ||
45
+ isAbsolute(relative) ||
46
+ parts.some((part) => part === ".." ||
47
+ part.toLowerCase() === ".git" ||
48
+ /^\.env(?:\.|$)/i.test(part) ||
49
+ CREDENTIAL_FILENAME.test(part))) {
50
+ throw pathDenied(resPath);
51
+ }
52
+ const candidate = resolve(identity.rootRealPath, relative);
53
+ if (!isContained(identity.rootRealPath, candidate)) {
54
+ throw pathDenied(resPath);
55
+ }
56
+ let anchor;
57
+ try {
58
+ anchor =
59
+ mode === "read"
60
+ ? await realpath(candidate)
61
+ : await nearestExistingRealParent(candidate, identity.rootRealPath);
62
+ }
63
+ catch (error) {
64
+ if (error instanceof GodotMcpException) {
65
+ throw error;
66
+ }
67
+ throw pathDenied(resPath);
68
+ }
69
+ if (!isContained(identity.rootRealPath, anchor)) {
70
+ throw pathDenied(resPath);
71
+ }
72
+ return candidate;
73
+ }
74
+ //# sourceMappingURL=pathPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathPolicy.js","sourceRoot":"","sources":["../../src/project/pathPolicy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { z } from "zod";
2
+ export declare const ProjectConfigSchema: z.ZodObject<{
3
+ schemaVersion: z.ZodLiteral<1>;
4
+ projectId: z.ZodUUID;
5
+ addonVersion: z.ZodLiteral<"0.1.0">;
6
+ allowedResourceRoots: z.ZodDefault<z.ZodArray<z.ZodString>>;
7
+ }, z.core.$strip>;
8
+ export type ProjectConfig = z.infer<typeof ProjectConfigSchema>;
9
+ export declare function createProjectConfig(root: string): Promise<ProjectConfig>;
10
+ //# sourceMappingURL=projectConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../src/project/projectConfig.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,mBAAmB;;;;;iBAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA6BhE,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAuB9E"}