noodleseed-cli 0.1.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/LICENSE +176 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +625 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +52 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/control-plane.d.ts +33 -0
- package/dist/control-plane.d.ts.map +1 -0
- package/dist/control-plane.js +223 -0
- package/dist/control-plane.js.map +1 -0
- package/dist/deploy.d.ts +62 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +182 -0
- package/dist/deploy.js.map +1 -0
- package/dist/dev.d.ts +50 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +223 -0
- package/dist/dev.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/validate.d.ts +37 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +46 -0
- package/dist/validate.js.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/index.d.ts +14 -0
- package/node_modules/@noodle-borg/auth/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/index.js +14 -0
- package/node_modules/@noodle-borg/auth/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts +21 -0
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js +24 -0
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/metadata.d.ts +27 -0
- package/node_modules/@noodle-borg/auth/dist/metadata.d.ts.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/metadata.js +21 -0
- package/node_modules/@noodle-borg/auth/dist/metadata.js.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/signer.d.ts +45 -0
- package/node_modules/@noodle-borg/auth/dist/signer.d.ts.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/signer.js +47 -0
- package/node_modules/@noodle-borg/auth/dist/signer.js.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/verify.d.ts +42 -0
- package/node_modules/@noodle-borg/auth/dist/verify.d.ts.map +1 -0
- package/node_modules/@noodle-borg/auth/dist/verify.js +48 -0
- package/node_modules/@noodle-borg/auth/dist/verify.js.map +1 -0
- package/node_modules/@noodle-borg/auth/package.json +27 -0
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +200 -0
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/authoring/dist/index.js +504 -0
- package/node_modules/@noodle-borg/authoring/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/authoring/package.json +29 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +203 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.js +20 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/in-memory.d.ts +13 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/in-memory.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/in-memory.js +19 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/in-memory.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/signature.d.ts +11 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/signature.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/signature.js +31 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/signature.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/types.d.ts +43 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/types.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/types.js +11 -0
- package/node_modules/@noodle-borg/compiler/dist/catalog/types.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/cli.d.ts +3 -0
- package/node_modules/@noodle-borg/compiler/dist/cli.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/cli.js +19 -0
- package/node_modules/@noodle-borg/compiler/dist/cli.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/compile.d.ts +50 -0
- package/node_modules/@noodle-borg/compiler/dist/compile.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/compile.js +719 -0
- package/node_modules/@noodle-borg/compiler/dist/compile.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +27 -0
- package/node_modules/@noodle-borg/compiler/dist/errors.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/errors.js +2 -0
- package/node_modules/@noodle-borg/compiler/dist/errors.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/index.d.ts +13 -0
- package/node_modules/@noodle-borg/compiler/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/index.js +11 -0
- package/node_modules/@noodle-borg/compiler/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/expression.d.ts +136 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/expression.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/expression.js +552 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/expression.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/naming.d.ts +14 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/naming.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/naming.js +18 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/naming.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema-refs.d.ts +24 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema-refs.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema-refs.js +149 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema-refs.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +97 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +157 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/schema-export.d.ts +6 -0
- package/node_modules/@noodle-borg/compiler/dist/schema-export.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/schema-export.js +28 -0
- package/node_modules/@noodle-borg/compiler/dist/schema-export.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/suggest.d.ts +41 -0
- package/node_modules/@noodle-borg/compiler/dist/suggest.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/suggest.js +105 -0
- package/node_modules/@noodle-borg/compiler/dist/suggest.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/uri-template.d.ts +33 -0
- package/node_modules/@noodle-borg/compiler/dist/uri-template.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compiler/dist/uri-template.js +83 -0
- package/node_modules/@noodle-borg/compiler/dist/uri-template.js.map +1 -0
- package/node_modules/@noodle-borg/compiler/package.json +32 -0
- package/node_modules/@noodle-borg/compute/dist/code-connector.d.ts +45 -0
- package/node_modules/@noodle-borg/compute/dist/code-connector.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/code-connector.js +53 -0
- package/node_modules/@noodle-borg/compute/dist/code-connector.js.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/engine.d.ts +73 -0
- package/node_modules/@noodle-borg/compute/dist/engine.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/engine.js +31 -0
- package/node_modules/@noodle-borg/compute/dist/engine.js.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/index.d.ts +4 -0
- package/node_modules/@noodle-borg/compute/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/index.js +4 -0
- package/node_modules/@noodle-borg/compute/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/quickjs-engine.d.ts +31 -0
- package/node_modules/@noodle-borg/compute/dist/quickjs-engine.d.ts.map +1 -0
- package/node_modules/@noodle-borg/compute/dist/quickjs-engine.js +271 -0
- package/node_modules/@noodle-borg/compute/dist/quickjs-engine.js.map +1 -0
- package/node_modules/@noodle-borg/compute/package.json +29 -0
- package/node_modules/@noodle-borg/connector-defs/dist/compile.d.ts +46 -0
- package/node_modules/@noodle-borg/connector-defs/dist/compile.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/dist/compile.js +289 -0
- package/node_modules/@noodle-borg/connector-defs/dist/compile.js.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/dist/index.d.ts +3 -0
- package/node_modules/@noodle-borg/connector-defs/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/dist/index.js +3 -0
- package/node_modules/@noodle-borg/connector-defs/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +332 -0
- package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/dist/schema.js +105 -0
- package/node_modules/@noodle-borg/connector-defs/dist/schema.js.map +1 -0
- package/node_modules/@noodle-borg/connector-defs/package.json +32 -0
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts +86 -0
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +138 -0
- package/node_modules/@noodle-borg/connector-http/dist/http-connector.js.map +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/index.d.ts +3 -0
- package/node_modules/@noodle-borg/connector-http/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/index.js +3 -0
- package/node_modules/@noodle-borg/connector-http/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.d.ts +45 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.d.ts.map +1 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.js +57 -0
- package/node_modules/@noodle-borg/connector-http/dist/ssrf.js.map +1 -0
- package/node_modules/@noodle-borg/connector-http/package.json +30 -0
- package/node_modules/@noodle-borg/protocol/dist/adapter.d.ts +73 -0
- package/node_modules/@noodle-borg/protocol/dist/adapter.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/adapter.js +2 -0
- package/node_modules/@noodle-borg/protocol/dist/adapter.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/adapters/mcp-2025-11-25.d.ts +19 -0
- package/node_modules/@noodle-borg/protocol/dist/adapters/mcp-2025-11-25.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/adapters/mcp-2025-11-25.js +34 -0
- package/node_modules/@noodle-borg/protocol/dist/adapters/mcp-2025-11-25.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/index.d.ts +5 -0
- package/node_modules/@noodle-borg/protocol/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/index.js +5 -0
- package/node_modules/@noodle-borg/protocol/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/jsonrpc.d.ts +19 -0
- package/node_modules/@noodle-borg/protocol/dist/jsonrpc.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/jsonrpc.js +14 -0
- package/node_modules/@noodle-borg/protocol/dist/jsonrpc.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/mapping.d.ts +133 -0
- package/node_modules/@noodle-borg/protocol/dist/mapping.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/mapping.js +181 -0
- package/node_modules/@noodle-borg/protocol/dist/mapping.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/negotiate.d.ts +13 -0
- package/node_modules/@noodle-borg/protocol/dist/negotiate.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/negotiate.js +18 -0
- package/node_modules/@noodle-borg/protocol/dist/negotiate.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/registry.d.ts +17 -0
- package/node_modules/@noodle-borg/protocol/dist/registry.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/registry.js +33 -0
- package/node_modules/@noodle-borg/protocol/dist/registry.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +22 -0
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.js +91 -0
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/server.d.ts +38 -0
- package/node_modules/@noodle-borg/protocol/dist/server.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/server.js +89 -0
- package/node_modules/@noodle-borg/protocol/dist/server.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/stateless.d.ts +14 -0
- package/node_modules/@noodle-borg/protocol/dist/stateless.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/stateless.js +28 -0
- package/node_modules/@noodle-borg/protocol/dist/stateless.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/bootstrap.d.ts +24 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/bootstrap.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/bootstrap.js +165 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/bootstrap.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/ext-apps-bundle.d.ts +4 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/ext-apps-bundle.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/ext-apps-bundle.js +10 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/ext-apps-bundle.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/inject.d.ts +8 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/inject.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/inject.js +36 -0
- package/node_modules/@noodle-borg/protocol/dist/widget/inject.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/package.json +29 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/map.d.ts +29 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/map.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/map.js +38 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/map.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/secret-box.d.ts +103 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/secret-box.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/secret-box.js +118 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/secret-box.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/static.d.ts +12 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/static.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/static.js +15 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/static.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts +28 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/types.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/types.js +2 -0
- package/node_modules/@noodle-borg/runtime/dist/broker/types.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/in-memory.d.ts +29 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/in-memory.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/in-memory.js +37 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/in-memory.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +41 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.js +2 -0
- package/node_modules/@noodle-borg/runtime/dist/connector/types.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/eval/evaluate.d.ts +39 -0
- package/node_modules/@noodle-borg/runtime/dist/eval/evaluate.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/eval/evaluate.js +117 -0
- package/node_modules/@noodle-borg/runtime/dist/eval/evaluate.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +47 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.js +297 -0
- package/node_modules/@noodle-borg/runtime/dist/execute.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts +12 -0
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/index.js +8 -0
- package/node_modules/@noodle-borg/runtime/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/allow-all.d.ts +10 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/allow-all.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/allow-all.js +13 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/allow-all.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/types.d.ts +25 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/types.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/types.js +2 -0
- package/node_modules/@noodle-borg/runtime/dist/policy/types.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/result.d.ts +19 -0
- package/node_modules/@noodle-borg/runtime/dist/result.d.ts.map +1 -0
- package/node_modules/@noodle-borg/runtime/dist/result.js +2 -0
- package/node_modules/@noodle-borg/runtime/dist/result.js.map +1 -0
- package/node_modules/@noodle-borg/runtime/package.json +27 -0
- package/node_modules/@noodle-borg/service/dist/auth/deploy-gate.d.ts +48 -0
- package/node_modules/@noodle-borg/service/dist/auth/deploy-gate.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/auth/deploy-gate.js +79 -0
- package/node_modules/@noodle-borg/service/dist/auth/deploy-gate.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/index.d.ts +7 -0
- package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/index.js +7 -0
- package/node_modules/@noodle-borg/service/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/main.d.ts +3 -0
- package/node_modules/@noodle-borg/service/dist/main.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/main.js +171 -0
- package/node_modules/@noodle-borg/service/dist/main.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts +14 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.js +48 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/consent.d.ts +18 -0
- package/node_modules/@noodle-borg/service/dist/oauth/consent.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/consent.js +55 -0
- package/node_modules/@noodle-borg/service/dist/oauth/consent.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/google.d.ts +31 -0
- package/node_modules/@noodle-borg/service/dist/oauth/google.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/google.js +39 -0
- package/node_modules/@noodle-borg/service/dist/oauth/google.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/paths.d.ts +3 -0
- package/node_modules/@noodle-borg/service/dist/oauth/paths.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/paths.js +19 -0
- package/node_modules/@noodle-borg/service/dist/oauth/paths.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts +61 -0
- package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/provider.js +313 -0
- package/node_modules/@noodle-borg/service/dist/oauth/provider.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store-postgres.d.ts +29 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store-postgres.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store-postgres.js +176 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store-postgres.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts +85 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store.js +57 -0
- package/node_modules/@noodle-borg/service/dist/oauth/store.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/tokens.d.ts +8 -0
- package/node_modules/@noodle-borg/service/dist/oauth/tokens.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/tokens.js +13 -0
- package/node_modules/@noodle-borg/service/dist/oauth/tokens.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/secret/kms-master-key.d.ts +36 -0
- package/node_modules/@noodle-borg/service/dist/secret/kms-master-key.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/secret/kms-master-key.js +51 -0
- package/node_modules/@noodle-borg/service/dist/secret/kms-master-key.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/service.d.ts +221 -0
- package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/service.js +1163 -0
- package/node_modules/@noodle-borg/service/dist/service.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/cloudsql-pool.d.ts +34 -0
- package/node_modules/@noodle-borg/service/dist/store/cloudsql-pool.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/cloudsql-pool.js +38 -0
- package/node_modules/@noodle-borg/service/dist/store/cloudsql-pool.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +56 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres.js +372 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store.d.ts +192 -0
- package/node_modules/@noodle-borg/service/dist/store.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store.js +230 -0
- package/node_modules/@noodle-borg/service/dist/store.js.map +1 -0
- package/node_modules/@noodle-borg/service/package.json +44 -0
- package/node_modules/@noodle-borg/transport-http/dist/caller-auth.d.ts +15 -0
- package/node_modules/@noodle-borg/transport-http/dist/caller-auth.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/caller-auth.js +38 -0
- package/node_modules/@noodle-borg/transport-http/dist/caller-auth.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/examples/serve-demo.d.ts +2 -0
- package/node_modules/@noodle-borg/transport-http/dist/examples/serve-demo.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/examples/serve-demo.js +129 -0
- package/node_modules/@noodle-borg/transport-http/dist/examples/serve-demo.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/front-door.d.ts +46 -0
- package/node_modules/@noodle-borg/transport-http/dist/front-door.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/front-door.js +75 -0
- package/node_modules/@noodle-borg/transport-http/dist/front-door.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts +142 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.js +387 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.d.ts +6 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.js +6 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/logging.d.ts +41 -0
- package/node_modules/@noodle-borg/transport-http/dist/logging.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/logging.js +71 -0
- package/node_modules/@noodle-borg/transport-http/dist/logging.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/serve.d.ts +22 -0
- package/node_modules/@noodle-borg/transport-http/dist/serve.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/serve.js +25 -0
- package/node_modules/@noodle-borg/transport-http/dist/serve.js.map +1 -0
- package/node_modules/@noodle-borg/transport-http/package.json +30 -0
- package/package.json +78 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Why a tool call could not be fulfilled. Internal contract — the protocol adapter maps these to
|
|
2
|
+
* the MCP wire shape in a later slice. */
|
|
3
|
+
export type ExecutionErrorCode = 'shape_only_artifact' | 'unknown_tool' | 'unknown_resource' | 'unknown_prompt' | 'unsupported_fulfilment' | 'connector_unavailable' | 'credential_unavailable' | 'signature_drift' | 'policy_denied' | 'policy_error' | 'arg_invalid' | 'expression_error' | 'connector_error' | 'output_invalid';
|
|
4
|
+
/** A typed execution failure. `path` locates the offending field/expression when applicable and
|
|
5
|
+
* never carries a sensitive value. */
|
|
6
|
+
export interface ExecutionError {
|
|
7
|
+
readonly code: ExecutionErrorCode;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly path?: string;
|
|
10
|
+
}
|
|
11
|
+
/** The result of executing a tool call: the operation output, or a typed error. */
|
|
12
|
+
export type ExecutionResult = {
|
|
13
|
+
readonly ok: true;
|
|
14
|
+
readonly output: unknown;
|
|
15
|
+
} | {
|
|
16
|
+
readonly ok: false;
|
|
17
|
+
readonly error: ExecutionError;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA;0CAC0C;AAC1C,MAAM,MAAM,kBAAkB,GAC1B,qBAAqB,GACrB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,GAChB,wBAAwB,GACxB,uBAAuB,GACvB,wBAAwB,GACxB,iBAAiB,GACjB,eAAe,GACf,cAAc,GACd,aAAa,GACb,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,CAAC;AAErB;sCACsC;AACtC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,mFAAmF;AACnF,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@noodle-borg/runtime",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@noodle-borg/compiler": "0.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^24.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* Authorizes the deploy control plane. This is an **admin** boundary — who may publish a
|
|
4
|
+
* server — distinct from tenant MCP caller auth (Slice 24) and from end-user
|
|
5
|
+
* OAuth (Phase 3, [ADR 0018](../../../../docs/decisions/0018-thread-verified-end-user-identity.md)).
|
|
6
|
+
* See [ADR 0029](../../../../docs/decisions/0029-deploy-authentication.md).
|
|
7
|
+
*/
|
|
8
|
+
export interface ControlPlaneIdentity {
|
|
9
|
+
readonly subject: string;
|
|
10
|
+
readonly email: string;
|
|
11
|
+
readonly superAdmin: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type ControlPlaneAuthResult = {
|
|
14
|
+
readonly ok: true;
|
|
15
|
+
readonly identity?: ControlPlaneIdentity;
|
|
16
|
+
} | {
|
|
17
|
+
readonly ok: false;
|
|
18
|
+
readonly status: 401 | 403;
|
|
19
|
+
readonly message: string;
|
|
20
|
+
};
|
|
21
|
+
export interface DeployAuthGate {
|
|
22
|
+
/** Authorize a control-plane request before reading a sensitive request body. */
|
|
23
|
+
authorize(req: IncomingMessage): Promise<ControlPlaneAuthResult> | ControlPlaneAuthResult;
|
|
24
|
+
}
|
|
25
|
+
/** Extract a bearer token from the `Authorization` header (scheme case-insensitive), or `null`. */
|
|
26
|
+
export declare function bearerToken(req: IncomingMessage): string | null;
|
|
27
|
+
/** Constant-time equality over fixed-length SHA-256 digests, so neither value nor its length leaks. */
|
|
28
|
+
export declare function constantTimeEqual(a: string, b: string): boolean;
|
|
29
|
+
/** Allows every deploy — the localhost-dev default (safe only on a loopback bind). */
|
|
30
|
+
export declare function allowAllGate(): DeployAuthGate;
|
|
31
|
+
export interface GoogleIdTokenVerifier {
|
|
32
|
+
verify(token: string, audience: string): Promise<{
|
|
33
|
+
subject: string;
|
|
34
|
+
email: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export interface GoogleControlPlaneGateOptions {
|
|
38
|
+
readonly audience: string;
|
|
39
|
+
readonly admins: readonly string[];
|
|
40
|
+
readonly allowedEmailDomain?: string;
|
|
41
|
+
readonly verifier?: GoogleIdTokenVerifier;
|
|
42
|
+
}
|
|
43
|
+
export declare class GoogleControlPlaneGate implements DeployAuthGate {
|
|
44
|
+
#private;
|
|
45
|
+
constructor(options: GoogleControlPlaneGateOptions);
|
|
46
|
+
authorize(req: IncomingMessage): Promise<ControlPlaneAuthResult>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=deploy-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-gate.d.ts","sourceRoot":"","sources":["../../src/auth/deploy-gate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAC;CAC3F;AAED,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAK/D;AAED,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAI/D;AAED,sFAAsF;AACtF,wBAAgB,YAAY,IAAI,cAAc,CAE7C;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtF;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAC3C;AAED,qBAAa,sBAAuB,YAAW,cAAc;;gBAM/C,OAAO,EAAE,6BAA6B;IAU5C,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAsBvE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { OAuth2Client } from 'google-auth-library';
|
|
3
|
+
/** Extract a bearer token from the `Authorization` header (scheme case-insensitive), or `null`. */
|
|
4
|
+
export function bearerToken(req) {
|
|
5
|
+
const header = req.headers.authorization;
|
|
6
|
+
if (typeof header !== 'string')
|
|
7
|
+
return null;
|
|
8
|
+
const match = /^Bearer[ \t]+(.+)$/i.exec(header.trim());
|
|
9
|
+
return match?.[1]?.trim() ?? null;
|
|
10
|
+
}
|
|
11
|
+
/** Constant-time equality over fixed-length SHA-256 digests, so neither value nor its length leaks. */
|
|
12
|
+
export function constantTimeEqual(a, b) {
|
|
13
|
+
const da = createHash('sha256').update(a).digest();
|
|
14
|
+
const db = createHash('sha256').update(b).digest();
|
|
15
|
+
return timingSafeEqual(da, db);
|
|
16
|
+
}
|
|
17
|
+
/** Allows every deploy — the localhost-dev default (safe only on a loopback bind). */
|
|
18
|
+
export function allowAllGate() {
|
|
19
|
+
return { authorize: () => ({ ok: true }) };
|
|
20
|
+
}
|
|
21
|
+
export class GoogleControlPlaneGate {
|
|
22
|
+
#audience;
|
|
23
|
+
#admins;
|
|
24
|
+
#allowedEmailDomain;
|
|
25
|
+
#verifier;
|
|
26
|
+
constructor(options) {
|
|
27
|
+
if (options.audience.length === 0)
|
|
28
|
+
throw new Error('Google audience must be non-empty');
|
|
29
|
+
this.#audience = options.audience;
|
|
30
|
+
this.#admins = new Set(options.admins.map((value) => value.toLowerCase()));
|
|
31
|
+
this.#allowedEmailDomain = normalizeEmailDomain(options.allowedEmailDomain ?? '@noodleseed.com');
|
|
32
|
+
this.#verifier = options.verifier ?? new GoogleOAuthVerifier();
|
|
33
|
+
}
|
|
34
|
+
async authorize(req) {
|
|
35
|
+
const token = bearerToken(req);
|
|
36
|
+
if (token === null)
|
|
37
|
+
return { ok: false, status: 401, message: 'missing bearer token' };
|
|
38
|
+
let identity;
|
|
39
|
+
try {
|
|
40
|
+
identity = await this.#verifier.verify(token, this.#audience);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { ok: false, status: 401, message: 'invalid bearer token' };
|
|
44
|
+
}
|
|
45
|
+
const email = identity.email.toLowerCase();
|
|
46
|
+
if (!email.endsWith(this.#allowedEmailDomain)) {
|
|
47
|
+
return { ok: false, status: 403, message: 'email domain is not allowed' };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
ok: true,
|
|
51
|
+
identity: {
|
|
52
|
+
subject: identity.subject,
|
|
53
|
+
email,
|
|
54
|
+
superAdmin: this.#admins.has(identity.subject.toLowerCase()) || this.#admins.has(email),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function normalizeEmailDomain(value) {
|
|
60
|
+
const domain = value.trim().toLowerCase();
|
|
61
|
+
if (domain.length === 0)
|
|
62
|
+
throw new Error('allowed email domain must be non-empty');
|
|
63
|
+
return domain.startsWith('@') ? domain : `@${domain}`;
|
|
64
|
+
}
|
|
65
|
+
class GoogleOAuthVerifier {
|
|
66
|
+
#client = new OAuth2Client();
|
|
67
|
+
async verify(token, audience) {
|
|
68
|
+
const ticket = await this.#client.verifyIdToken({ idToken: token, audience });
|
|
69
|
+
const payload = ticket.getPayload();
|
|
70
|
+
const subject = payload?.sub;
|
|
71
|
+
const email = payload?.email;
|
|
72
|
+
const emailVerified = payload?.email_verified;
|
|
73
|
+
if (typeof subject !== 'string' || typeof email !== 'string' || emailVerified !== true) {
|
|
74
|
+
throw new Error('Google token is missing a verified subject/email');
|
|
75
|
+
}
|
|
76
|
+
return { subject, email };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=deploy-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-gate.js","sourceRoot":"","sources":["../../src/auth/deploy-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { allowAllGate, bearerToken, type ControlPlaneAuthResult, type ControlPlaneIdentity, constantTimeEqual, type DeployAuthGate, GoogleControlPlaneGate, type GoogleIdTokenVerifier, } from './auth/deploy-gate.js';
|
|
2
|
+
export { type GcpKmsConfig, gcpKmsMasterKeyProvider, type KmsClient, } from './secret/kms-master-key.js';
|
|
3
|
+
export { createServiceHandler, type DeployError, type DeployResult, type RecoverResult, type RunningService, ServerRegistry, type ServiceOptions, serveService, } from './service.js';
|
|
4
|
+
export { type CloudSqlConfig, createPostgresPool, type PostgresPool, type PostgresPoolConfig, } from './store/cloudsql-pool.js';
|
|
5
|
+
export { PostgresArtifactStore } from './store/postgres.js';
|
|
6
|
+
export { type ArtifactStore, type ControlPlaneStore, DEPLOYMENT_ID_PATTERN, type DeploymentSummary, type DeployRecord, InMemoryArtifactStore, InMemoryControlPlaneStore, JsonFileArtifactStore, type OrgMemberRecord, type OrgRecord, type OrgRole, type SecretEnvelope, SLUG_PATTERN, type TenantRef, validateOrgRole, validateSlug, validateTenantRef, } from './store.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,iBAAiB,EACjB,KAAK,cAAc,EACnB,sBAAsB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,YAAY,EACjB,uBAAuB,EACvB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,cAAc,EACnB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,YAAY,EACZ,KAAK,SAAS,EACd,eAAe,EACf,YAAY,EACZ,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { allowAllGate, bearerToken, constantTimeEqual, GoogleControlPlaneGate, } from './auth/deploy-gate.js';
|
|
2
|
+
export { gcpKmsMasterKeyProvider, } from './secret/kms-master-key.js';
|
|
3
|
+
export { createServiceHandler, ServerRegistry, serveService, } from './service.js';
|
|
4
|
+
export { createPostgresPool, } from './store/cloudsql-pool.js';
|
|
5
|
+
export { PostgresArtifactStore } from './store/postgres.js';
|
|
6
|
+
export { DEPLOYMENT_ID_PATTERN, InMemoryArtifactStore, InMemoryControlPlaneStore, JsonFileArtifactStore, SLUG_PATTERN, validateOrgRole, validateSlug, validateTenantRef, } from './store.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,WAAW,EAGX,iBAAiB,EAEjB,sBAAsB,GAEvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,uBAAuB,GAExB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EAKpB,cAAc,EAEd,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,kBAAkB,GAGnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAGL,qBAAqB,EAGrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EAKrB,YAAY,EAEZ,eAAe,EACf,YAAY,EACZ,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The Noodle deploy service: a single stateless process that accepts tenant-scoped deploys and serves each
|
|
4
|
+
* active app environment at `/o/{org}/{app}/mcp` or `/o/{org}/{app}/{env}/mcp`. Build the workspace, then run:
|
|
5
|
+
*
|
|
6
|
+
* node packages/service/dist/main.js # listens on http://127.0.0.1:8787
|
|
7
|
+
*
|
|
8
|
+
* Deploy a manifest with the `mrdn deploy` CLI, or POST one directly.
|
|
9
|
+
*/
|
|
10
|
+
import { createJwtVerifier, createStaticSigningKeyProvider } from '@noodle-borg/auth';
|
|
11
|
+
import { createLogger } from '@noodle-borg/transport-http';
|
|
12
|
+
import { GoogleOAuthAuthenticator } from './oauth/google.js';
|
|
13
|
+
import { serveService } from './service.js';
|
|
14
|
+
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
15
|
+
async function main() {
|
|
16
|
+
const port = Number(process.env.PORT ?? 8787);
|
|
17
|
+
const publicBaseUrl = process.env.PUBLIC_BASE_URL;
|
|
18
|
+
const host = process.env.HOST;
|
|
19
|
+
const googleClientId = process.env.NOODLE_GOOGLE_CLIENT_ID;
|
|
20
|
+
const controlPlaneAllowedEmailDomain = process.env.NOODLE_CONTROL_PLANE_ALLOWED_EMAIL_DOMAIN ?? '@noodleseed.com';
|
|
21
|
+
const controlPlaneAdmins = parseList(process.env.NOODLE_CONTROL_PLANE_ADMINS);
|
|
22
|
+
const dataDir = process.env.NOODLE_DATA_DIR;
|
|
23
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
24
|
+
const secretMasterKey = process.env.NOODLE_SECRET_MASTER_KEY;
|
|
25
|
+
// KEK custody (ADR 0037): a Cloud KMS cryptoKey resource name. Takes precedence over the static key — the
|
|
26
|
+
// KEK then never enters the process (KMS wraps a per-record data key).
|
|
27
|
+
const kmsKeyName = process.env.NOODLE_KMS_KEY;
|
|
28
|
+
// Cloud SQL (IAM DB auth) backend: a present INSTANCE_CONNECTION_NAME requires DB_USER + DB_NAME, else
|
|
29
|
+
// fail closed rather than silently fall back to in-memory on a cloud deploy that intended Postgres.
|
|
30
|
+
const instanceConnectionName = process.env.INSTANCE_CONNECTION_NAME;
|
|
31
|
+
let cloudSql;
|
|
32
|
+
if (instanceConnectionName !== undefined) {
|
|
33
|
+
const dbUser = process.env.DB_USER;
|
|
34
|
+
const dbName = process.env.DB_NAME;
|
|
35
|
+
if (!dbUser || !dbName) {
|
|
36
|
+
throw new Error('INSTANCE_CONNECTION_NAME requires DB_USER and DB_NAME (Cloud SQL IAM auth)');
|
|
37
|
+
}
|
|
38
|
+
const ipType = process.env.DB_IP_TYPE;
|
|
39
|
+
cloudSql = {
|
|
40
|
+
instanceConnectionName,
|
|
41
|
+
dbUser,
|
|
42
|
+
dbName,
|
|
43
|
+
...(ipType === 'PRIVATE' || ipType === 'PUBLIC' ? { ipType } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const envLevel = process.env.NOODLE_LOG_LEVEL;
|
|
47
|
+
const level = LOG_LEVELS.includes(envLevel)
|
|
48
|
+
? envLevel
|
|
49
|
+
: 'info';
|
|
50
|
+
const logger = createLogger({ level, base: { svc: 'noodle' } });
|
|
51
|
+
const trustProxy = process.env.NOODLE_TRUST_PROXY === '1' || process.env.NOODLE_TRUST_PROXY === 'true';
|
|
52
|
+
// Lazy recompile-on-first-request is the default (ADR 0036, multi-instance correctness). NOODLE_WARM_ALL
|
|
53
|
+
// opts into eager recompile-all-on-boot for a pinned single-instance / on-prem deploy.
|
|
54
|
+
const warmAll = process.env.NOODLE_WARM_ALL === '1' || process.env.NOODLE_WARM_ALL === 'true';
|
|
55
|
+
// Owner-only end-user auth. Two modes:
|
|
56
|
+
// • Self-hosted authorization server (OA-2, ADR 0042): set NOODLE_OAUTH_ISSUER + the Google OAuth client
|
|
57
|
+
// creds; the service runs the AS (DCR + PKCE, federating login to Google) and verifies owner-only tokens
|
|
58
|
+
// in-process against its own signing key. A standards client (Claude.ai/ChatGPT) can then sign in.
|
|
59
|
+
// • External issuer (OA-1): set NOODLE_OAUTH_ISSUER + NOODLE_OAUTH_JWKS_URI to validate tokens from an
|
|
60
|
+
// issuer you operate elsewhere; the runtime is only the resource server.
|
|
61
|
+
// With neither, owner-only endpoints fail closed (no verifier).
|
|
62
|
+
const oauthIssuer = process.env.NOODLE_OAUTH_ISSUER;
|
|
63
|
+
const oauthJwksUri = process.env.NOODLE_OAUTH_JWKS_URI;
|
|
64
|
+
const oauthGoogleClientId = process.env.NOODLE_OAUTH_GOOGLE_CLIENT_ID;
|
|
65
|
+
const oauthGoogleSecret = process.env.NOODLE_OAUTH_GOOGLE_CLIENT_SECRET;
|
|
66
|
+
const oauthGoogleRedirect = process.env.NOODLE_OAUTH_GOOGLE_REDIRECT_URI;
|
|
67
|
+
const oauthSigningKey = process.env.NOODLE_OAUTH_SIGNING_KEY;
|
|
68
|
+
const oauthAllowedEmailDomain = process.env.NOODLE_OAUTH_ALLOWED_EMAIL_DOMAIN;
|
|
69
|
+
const selfHostAuthServer = Boolean(oauthIssuer && oauthGoogleClientId && oauthGoogleSecret && oauthGoogleRedirect);
|
|
70
|
+
// Self-hosted AS config (OA-2): serveService runs the AS and derives the verifier from the signing key.
|
|
71
|
+
const oauth = selfHostAuthServer
|
|
72
|
+
? {
|
|
73
|
+
issuer: oauthIssuer,
|
|
74
|
+
signer: await createStaticSigningKeyProvider(oauthSigningKey ? { privateKeyPem: oauthSigningKey } : {}),
|
|
75
|
+
google: new GoogleOAuthAuthenticator({
|
|
76
|
+
clientId: oauthGoogleClientId,
|
|
77
|
+
clientSecret: oauthGoogleSecret,
|
|
78
|
+
redirectUri: oauthGoogleRedirect,
|
|
79
|
+
}),
|
|
80
|
+
...(oauthAllowedEmailDomain ? { allowedEmailDomain: oauthAllowedEmailDomain } : {}),
|
|
81
|
+
}
|
|
82
|
+
: undefined;
|
|
83
|
+
// External-issuer verifier (OA-1 only): used when not self-hosting the AS.
|
|
84
|
+
const verifyOwnerToken = !selfHostAuthServer && oauthIssuer && oauthJwksUri
|
|
85
|
+
? createJwtVerifier({ issuer: oauthIssuer, jwksUri: oauthJwksUri })
|
|
86
|
+
: undefined;
|
|
87
|
+
const running = await serveService({
|
|
88
|
+
port,
|
|
89
|
+
logger,
|
|
90
|
+
...(host ? { host } : {}),
|
|
91
|
+
...(publicBaseUrl ? { publicBaseUrl } : {}),
|
|
92
|
+
...(googleClientId ? { googleClientId } : {}),
|
|
93
|
+
...(googleClientId ? { controlPlaneAllowedEmailDomain } : {}),
|
|
94
|
+
...(controlPlaneAdmins.length > 0 ? { controlPlaneAdmins } : {}),
|
|
95
|
+
...(dataDir ? { dataDir } : {}),
|
|
96
|
+
...(databaseUrl ? { databaseUrl } : {}),
|
|
97
|
+
...(cloudSql ? { cloudSql } : {}),
|
|
98
|
+
...(secretMasterKey ? { secretMasterKey } : {}),
|
|
99
|
+
...(kmsKeyName ? { kmsKeyName } : {}),
|
|
100
|
+
...(warmAll ? { warmAll: true } : {}),
|
|
101
|
+
...(trustProxy ? { tls: { trustProxy: true } } : {}),
|
|
102
|
+
// Self-hosted AS: serveService derives authServerIssuer + the in-process verifier from `oauth`.
|
|
103
|
+
// External issuer: pass them explicitly.
|
|
104
|
+
...(oauth ? { oauth } : oauthIssuer ? { authServerIssuer: oauthIssuer } : {}),
|
|
105
|
+
...(verifyOwnerToken ? { verifyOwnerToken } : {}),
|
|
106
|
+
});
|
|
107
|
+
console.log(`Noodle deploy service listening at ${running.url}`);
|
|
108
|
+
console.log(googleClientId
|
|
109
|
+
? 'Control auth: Google ID token required; org membership gates deploys'
|
|
110
|
+
: 'Control auth: OPEN (localhost dev only — set NOODLE_GOOGLE_CLIENT_ID before exposing)');
|
|
111
|
+
const persistence = cloudSql
|
|
112
|
+
? `ON (Cloud SQL ${cloudSql.instanceConnectionName})`
|
|
113
|
+
: databaseUrl
|
|
114
|
+
? 'ON (Postgres)'
|
|
115
|
+
: dataDir
|
|
116
|
+
? `ON (data dir ${dataDir})`
|
|
117
|
+
: undefined;
|
|
118
|
+
const recoveryMode = warmAll ? 'eager warm-all' : 'lazy recompile';
|
|
119
|
+
const kekMode = kmsKeyName ? 'KMS-wrapped KEK' : 'static key';
|
|
120
|
+
console.log(persistence
|
|
121
|
+
? `Persistence: ${persistence} — deploys survive restart (${recoveryMode}), secrets sealed (${kekMode})`
|
|
122
|
+
: 'Persistence: OFF (in-memory; deploys lost on restart — set DATABASE_URL or NOODLE_DATA_DIR)');
|
|
123
|
+
console.log(trustProxy
|
|
124
|
+
? 'TLS posture: proxy-terminated (trusting X-Forwarded-Proto; HTTPS enforced + HSTS)'
|
|
125
|
+
: 'TLS posture: direct/dev (security headers only) — set NOODLE_TRUST_PROXY behind a TLS proxy');
|
|
126
|
+
console.log(oauth
|
|
127
|
+
? `Owner auth: self-hosted authorization server at ${oauthIssuer} (DCR + PKCE, Google login)`
|
|
128
|
+
: verifyOwnerToken
|
|
129
|
+
? `Owner auth: owner-only deploys validate tokens from external issuer ${oauthIssuer}`
|
|
130
|
+
: 'Owner auth: OFF (owner-only deploys fail closed — set NOODLE_OAUTH_ISSUER + Google OAuth creds, or NOODLE_OAUTH_JWKS_URI)');
|
|
131
|
+
if (running.recovered) {
|
|
132
|
+
const { recovered, failed } = running.recovered;
|
|
133
|
+
console.log(`Recovered: ${recovered} server(s)${failed.length ? `, ${failed.length} skipped (failed to recompile)` : ''}`);
|
|
134
|
+
}
|
|
135
|
+
console.log(`Deploy a manifest: POST ${running.url}/v1/orgs/<org>/apps/<app>/envs/prod/deploy body {"manifest":"<yaml>"}`);
|
|
136
|
+
console.log(`Tenant MCP routes are served at ${running.url}/o/<org>/<app>/mcp`);
|
|
137
|
+
// Graceful drain (ADR 0034): on SIGTERM (Cloud Run sends it before stopping an instance) stop accepting
|
|
138
|
+
// new connections, let in-flight requests finish, close the DB pool, then exit. A bounded timer
|
|
139
|
+
// force-exits if the drain hangs so a stuck connection never blocks the rollout.
|
|
140
|
+
let draining = false;
|
|
141
|
+
const shutdown = async (signal) => {
|
|
142
|
+
if (draining)
|
|
143
|
+
return;
|
|
144
|
+
draining = true;
|
|
145
|
+
logger.info('shutdown', { signal });
|
|
146
|
+
const force = setTimeout(() => process.exit(1), 10_000);
|
|
147
|
+
force.unref();
|
|
148
|
+
try {
|
|
149
|
+
running.http.closeIdleConnections();
|
|
150
|
+
await running.close();
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
logger.error('shutdown.error', { message: error.message });
|
|
154
|
+
}
|
|
155
|
+
clearTimeout(force);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
};
|
|
158
|
+
process.once('SIGTERM', () => void shutdown('SIGTERM'));
|
|
159
|
+
process.once('SIGINT', () => void shutdown('SIGINT'));
|
|
160
|
+
}
|
|
161
|
+
main().catch((error) => {
|
|
162
|
+
console.error(error);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
165
|
+
function parseList(value) {
|
|
166
|
+
return (value ?? '')
|
|
167
|
+
.split(',')
|
|
168
|
+
.map((item) => item.trim())
|
|
169
|
+
.filter((item) => item.length > 0);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Express } from 'express';
|
|
2
|
+
import type { NoodleOAuthProvider } from './provider.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build the minimal Express sub-app for the self-hosted authorization server (OA-2,
|
|
5
|
+
* [ADR 0042](../../../../docs/decisions/0042-self-hosted-oauth-authorization-server.md)). It composes the MCP
|
|
6
|
+
* SDK's **individual** handlers — `authorize`, `token`, `register` (DCR) — rather than the whole
|
|
7
|
+
* `mcpAuthRouter`, because that router's protected-resource metadata is single-resource and we keep OA-1's
|
|
8
|
+
* dynamic per-tenant PRM in the raw `node:http` front-door. Authorization-server metadata (RFC 8414) + JWKS +
|
|
9
|
+
* the Google callback + the consent endpoint are added here. The app is a `(req, res)` listener the
|
|
10
|
+
* front-door delegates to for {@link isAuthServerPath} paths.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createOAuthApp(provider: NoodleOAuthProvider): Express;
|
|
13
|
+
export { isAuthServerPath } from './paths.js';
|
|
14
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/oauth/app.ts"],"names":[],"mappings":"AAGA,OAAgB,EAAE,KAAK,OAAO,EAA+B,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAgCrE;AAWD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { authorizationHandler } from '@modelcontextprotocol/sdk/server/auth/handlers/authorize.js';
|
|
2
|
+
import { clientRegistrationHandler } from '@modelcontextprotocol/sdk/server/auth/handlers/register.js';
|
|
3
|
+
import { tokenHandler } from '@modelcontextprotocol/sdk/server/auth/handlers/token.js';
|
|
4
|
+
import express, {} from 'express';
|
|
5
|
+
/**
|
|
6
|
+
* Build the minimal Express sub-app for the self-hosted authorization server (OA-2,
|
|
7
|
+
* [ADR 0042](../../../../docs/decisions/0042-self-hosted-oauth-authorization-server.md)). It composes the MCP
|
|
8
|
+
* SDK's **individual** handlers — `authorize`, `token`, `register` (DCR) — rather than the whole
|
|
9
|
+
* `mcpAuthRouter`, because that router's protected-resource metadata is single-resource and we keep OA-1's
|
|
10
|
+
* dynamic per-tenant PRM in the raw `node:http` front-door. Authorization-server metadata (RFC 8414) + JWKS +
|
|
11
|
+
* the Google callback + the consent endpoint are added here. The app is a `(req, res)` listener the
|
|
12
|
+
* front-door delegates to for {@link isAuthServerPath} paths.
|
|
13
|
+
*/
|
|
14
|
+
export function createOAuthApp(provider) {
|
|
15
|
+
const app = express();
|
|
16
|
+
app.disable('x-powered-by');
|
|
17
|
+
app.use('/authorize', authorizationHandler({ provider }));
|
|
18
|
+
app.use('/token', tokenHandler({ provider }));
|
|
19
|
+
app.use('/register', clientRegistrationHandler({ clientsStore: provider.clientsStore }));
|
|
20
|
+
// RFC 8414 AS metadata + JWKS — fetched cross-origin by web MCP clients, so allow any origin.
|
|
21
|
+
app.get('/.well-known/oauth-authorization-server', allowCors, (_req, res) => {
|
|
22
|
+
res.json(provider.metadata());
|
|
23
|
+
});
|
|
24
|
+
app.get('/.well-known/jwks.json', allowCors, (_req, res) => {
|
|
25
|
+
void provider
|
|
26
|
+
.jwks()
|
|
27
|
+
.then((jwks) => res.json(jwks))
|
|
28
|
+
.catch(() => res.status(500).json({ error: 'server_error' }));
|
|
29
|
+
});
|
|
30
|
+
// Google federation callback + the mandatory consent decision (confused-deputy mitigation).
|
|
31
|
+
app.get('/oauth/google/callback', (req, res) => {
|
|
32
|
+
void provider.handleGoogleCallback(req, res).catch(() => failPlain(res));
|
|
33
|
+
});
|
|
34
|
+
app.post('/oauth/consent', express.urlencoded({ extended: false }), (req, res) => {
|
|
35
|
+
void provider.handleConsent(req, res).catch(() => failPlain(res));
|
|
36
|
+
});
|
|
37
|
+
return app;
|
|
38
|
+
}
|
|
39
|
+
function allowCors(_req, res, next) {
|
|
40
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
41
|
+
next();
|
|
42
|
+
}
|
|
43
|
+
function failPlain(res) {
|
|
44
|
+
if (!res.headersSent)
|
|
45
|
+
res.status(500).type('text/plain').send('internal error');
|
|
46
|
+
}
|
|
47
|
+
export { isAuthServerPath } from './paths.js';
|
|
48
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/oauth/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6DAA6D,CAAC;AACnG,OAAO,EAAE,yBAAyB,EAAE,MAAM,4DAA4D,CAAC;AACvG,OAAO,EAAE,YAAY,EAAE,MAAM,yDAAyD,CAAC;AACvF,OAAO,OAAO,EAAE,EAA6C,MAAM,SAAS,CAAC;AAG7E;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,QAA6B;IAC1D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAE5B,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,oBAAoB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1D,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC9C,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,yBAAyB,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IAEzF,8FAA8F;IAC9F,GAAG,CAAC,GAAG,CAAC,yCAAyC,EAAE,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAC7F,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,SAAS,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAC5E,KAAK,QAAQ;aACV,IAAI,EAAE;aACN,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC9B,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,4FAA4F;IAC5F,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAChE,KAAK,QAAQ,CAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,CACN,gBAAgB,EAChB,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EACvC,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAC9B,KAAK,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC,CACF,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,IAAa,EAAE,GAAa,EAAE,IAAgB;IAC/D,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,IAAI,EAAE,CAAC;AACT,CAAC;AAED,SAAS,SAAS,CAAC,GAAa;IAC9B,IAAI,CAAC,GAAG,CAAC,WAAW;QAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAClF,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The consent interstitial (OA-2, [ADR 0042]). **Required**, not optional: because the authorization server
|
|
3
|
+
* federates every dynamically-registered client through one static Google client, the MCP 2025-11-25 spec
|
|
4
|
+
* mandates explicit per-client user consent before issuing a code (confused-deputy mitigation). The page
|
|
5
|
+
* shows the requesting client and where the code will be sent, so the owner can refuse an unfamiliar app.
|
|
6
|
+
*/
|
|
7
|
+
export interface ConsentPageInput {
|
|
8
|
+
readonly clientName: string;
|
|
9
|
+
readonly resourceHost: string;
|
|
10
|
+
readonly redirectHost: string;
|
|
11
|
+
readonly userEmail: string;
|
|
12
|
+
/** Signed, short-lived token carrying the full authorization context (tamper-proof). */
|
|
13
|
+
readonly consentToken: string;
|
|
14
|
+
/** Where the Approve/Deny form POSTs (the AS consent endpoint). */
|
|
15
|
+
readonly consentAction: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function renderConsentPage(input: ConsentPageInput): string;
|
|
18
|
+
//# sourceMappingURL=consent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/oauth/consent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAWD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CA6CjE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
function esc(value) {
|
|
2
|
+
return value
|
|
3
|
+
.replace(/&/g, '&')
|
|
4
|
+
.replace(/</g, '<')
|
|
5
|
+
.replace(/>/g, '>')
|
|
6
|
+
.replace(/"/g, '"')
|
|
7
|
+
.replace(/'/g, ''');
|
|
8
|
+
}
|
|
9
|
+
export function renderConsentPage(input) {
|
|
10
|
+
const client = esc(input.clientName);
|
|
11
|
+
const resource = esc(input.resourceHost);
|
|
12
|
+
const redirect = esc(input.redirectHost);
|
|
13
|
+
const email = esc(input.userEmail);
|
|
14
|
+
const token = esc(input.consentToken);
|
|
15
|
+
const action = esc(input.consentAction);
|
|
16
|
+
return `<!doctype html>
|
|
17
|
+
<html lang="en">
|
|
18
|
+
<head>
|
|
19
|
+
<meta charset="utf-8" />
|
|
20
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
21
|
+
<title>Authorize access</title>
|
|
22
|
+
<style>
|
|
23
|
+
:root { color-scheme: light dark; }
|
|
24
|
+
body { font: 15px/1.5 system-ui, sans-serif; max-width: 30rem; margin: 4rem auto; padding: 0 1rem; }
|
|
25
|
+
.card { border: 1px solid #8884; border-radius: 12px; padding: 1.5rem; }
|
|
26
|
+
h1 { font-size: 1.15rem; margin: 0 0 1rem; }
|
|
27
|
+
dl { margin: 1rem 0; }
|
|
28
|
+
dt { color: #888; font-size: .8rem; }
|
|
29
|
+
dd { margin: 0 0 .75rem; font-weight: 600; word-break: break-all; }
|
|
30
|
+
.row { display: flex; gap: .75rem; margin-top: 1.5rem; }
|
|
31
|
+
button { flex: 1; padding: .6rem 1rem; border-radius: 8px; border: 1px solid #8884; font: inherit; cursor: pointer; }
|
|
32
|
+
button.approve { background: #1d9e75; color: #fff; border-color: #1d9e75; }
|
|
33
|
+
</style>
|
|
34
|
+
</head>
|
|
35
|
+
<body>
|
|
36
|
+
<div class="card">
|
|
37
|
+
<h1>Authorize access to your server</h1>
|
|
38
|
+
<p>The application <strong>${client}</strong> is requesting access to your Noodle MCP server, acting as <strong>${email}</strong>.</p>
|
|
39
|
+
<dl>
|
|
40
|
+
<dt>MCP server</dt><dd>${resource}</dd>
|
|
41
|
+
<dt>Sign-in will redirect to</dt><dd>${redirect}</dd>
|
|
42
|
+
</dl>
|
|
43
|
+
<p>Only approve if you recognize this application.</p>
|
|
44
|
+
<form method="post" action="${action}">
|
|
45
|
+
<input type="hidden" name="consent_token" value="${token}" />
|
|
46
|
+
<div class="row">
|
|
47
|
+
<button type="submit" name="decision" value="deny">Deny</button>
|
|
48
|
+
<button type="submit" name="decision" value="approve" class="approve">Approve</button>
|
|
49
|
+
</div>
|
|
50
|
+
</form>
|
|
51
|
+
</div>
|
|
52
|
+
</body>
|
|
53
|
+
</html>`;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=consent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/oauth/consent.ts"],"names":[],"mappings":"AAiBA,SAAS,GAAG,CAAC,KAAa;IACxB,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACxC,OAAO;;;;;;;;;;;;;;;;;;;;;;iCAsBwB,MAAM,+EAA+E,KAAK;;+BAE5F,QAAQ;6CACM,QAAQ;;;kCAGnB,MAAM;yDACiB,KAAK;;;;;;;;QAQtD,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** A verified upstream human identity from "Sign in with Google". */
|
|
2
|
+
export interface GoogleIdentity {
|
|
3
|
+
readonly subject: string;
|
|
4
|
+
readonly email: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The Google-federation leg of the authorization server (OA-2,
|
|
8
|
+
* [ADR 0042](../../../../docs/decisions/0042-self-hosted-oauth-authorization-server.md)): the AS authenticates
|
|
9
|
+
* the human via Google, then issues its own Noodle tokens. Injectable so tests can supply a fake without a
|
|
10
|
+
* live Google round-trip; production uses {@link GoogleOAuthAuthenticator} (`google-auth-library`, the same
|
|
11
|
+
* library the control plane already uses — [ADR 0039]).
|
|
12
|
+
*/
|
|
13
|
+
export interface GoogleAuthenticator {
|
|
14
|
+
/** The "Sign in with Google" URL to redirect the user-agent to, carrying our `state` nonce. */
|
|
15
|
+
authorizationUrl(state: string): string;
|
|
16
|
+
/** Exchange Google's authorization `code` for the verified user identity (or throw on failure). */
|
|
17
|
+
exchange(code: string): Promise<GoogleIdentity>;
|
|
18
|
+
}
|
|
19
|
+
export interface GoogleOAuthConfig {
|
|
20
|
+
readonly clientId: string;
|
|
21
|
+
readonly clientSecret: string;
|
|
22
|
+
/** The AS's own Google callback URL (e.g. `https://borg.noodleseed.com/oauth/google/callback`). */
|
|
23
|
+
readonly redirectUri: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class GoogleOAuthAuthenticator implements GoogleAuthenticator {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(config: GoogleOAuthConfig);
|
|
28
|
+
authorizationUrl(state: string): string;
|
|
29
|
+
exchange(code: string): Promise<GoogleIdentity>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/oauth/google.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,+FAA+F;IAC/F,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC,mGAAmG;IACnG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mGAAmG;IACnG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,wBAAyB,YAAW,mBAAmB;;gBAItD,MAAM,EAAE,iBAAiB;IASrC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAWjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CActD"}
|