toolcraft 0.0.27 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.compile-check.js +7 -1
- package/dist/cli.d.ts +9 -1
- package/dist/cli.js +134 -62
- package/dist/design.d.ts +1 -0
- package/dist/design.js +1 -0
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +6 -0
- package/dist/human-in-loop/approvals-commands.js +2 -1
- package/dist/human-in-loop/runner.js +2 -2
- package/dist/index.d.ts +6 -2
- package/dist/json-schema-converter.js +12 -1
- package/dist/mcp-proxy.js +26 -9
- package/dist/mcp.js +55 -4
- package/dist/renderer.js +1 -1
- package/dist/schema-scope.js +22 -1
- package/dist/sdk.js +51 -3
- package/dist/source-snippet.js +1 -1
- package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +5 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +10 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/cursor.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +15 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +1 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/index.d.ts +1 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/index.js +1 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +5 -0
- package/node_modules/@poe-code/agent-defs/dist/index.d.ts +2 -2
- package/node_modules/@poe-code/agent-defs/dist/index.js +1 -1
- package/node_modules/@poe-code/agent-defs/dist/registry.js +8 -1
- package/node_modules/@poe-code/agent-defs/dist/specifier.js +7 -3
- package/node_modules/@poe-code/agent-defs/dist/types.d.ts +5 -0
- package/node_modules/@poe-code/agent-human-in-loop/dist/providers/osascript.js +7 -1
- package/node_modules/@poe-code/agent-mcp-config/dist/configs.js +6 -0
- package/node_modules/@poe-code/config-mutations/dist/error-codes.d.ts +1 -0
- package/node_modules/@poe-code/config-mutations/dist/error-codes.js +6 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.js +25 -15
- package/node_modules/@poe-code/config-mutations/dist/formats/json.js +1 -1
- package/node_modules/@poe-code/config-mutations/dist/formats/toml.js +1 -1
- package/node_modules/@poe-code/config-mutations/dist/formats/yaml.js +1 -1
- package/node_modules/@poe-code/config-mutations/dist/fs-utils.js +2 -4
- package/node_modules/@poe-code/config-mutations/dist/template/render.js +1 -1
- package/node_modules/@poe-code/config-mutations/package.json +1 -1
- package/node_modules/@poe-code/process-runner/dist/host/host-execution-env.js +18 -5
- package/node_modules/@poe-code/process-runner/dist/host/host-runner.js +38 -4
- package/node_modules/@poe-code/process-runner/dist/workspace-transfer.js +8 -2
- package/node_modules/@poe-code/task-list/dist/backends/gh-issues-sync.js +10 -7
- package/node_modules/@poe-code/task-list/dist/backends/markdown-dir.js +13 -6
- package/node_modules/@poe-code/task-list/dist/backends/utils.js +15 -10
- package/node_modules/@poe-code/task-list/dist/backends/yaml-file.js +39 -22
- package/node_modules/@poe-code/task-list/dist/move.js +4 -1
- package/node_modules/@poe-code/task-list/dist/open.js +42 -20
- package/node_modules/@poe-code/task-list/dist/state-machine.js +8 -5
- package/node_modules/auth-store/dist/create-secret-store.js +6 -1
- package/node_modules/auth-store/dist/encrypted-file-store.d.ts +1 -1
- package/node_modules/auth-store/dist/encrypted-file-store.js +32 -28
- package/node_modules/auth-store/dist/error-codes.d.ts +1 -0
- package/node_modules/auth-store/dist/error-codes.js +5 -0
- package/node_modules/auth-store/dist/keychain-store.js +23 -8
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +17 -5
- package/node_modules/mcp-oauth/dist/client/authorization-state.js +21 -8
- package/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +128 -55
- package/node_modules/mcp-oauth/dist/client/token-endpoint.js +27 -17
- package/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js +43 -22
- package/node_modules/toolcraft-design/README.md +148 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.d.ts +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.js +12 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.d.ts +1 -1
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.js +1 -1
- package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
- package/node_modules/toolcraft-design/dist/components/catalog.js +94 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.d.ts +2 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.js +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.js +1 -2
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.js +16 -19
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.js +1 -15
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.js +2 -2
- package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.d.ts +7 -1
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.js +4 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.d.ts +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.js +28 -6
- package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/theme.d.ts +1 -1
- package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.js +50 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.d.ts +2 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.js +1 -0
- package/node_modules/toolcraft-design/package.json +42 -0
- package/package.json +10 -6
- package/node_modules/@poe-code/design-system/dist/explorer/theme.js +0 -97
- package/node_modules/@poe-code/design-system/dist/prompts/theme.js +0 -12
- package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +0 -35
- package/node_modules/@poe-code/design-system/dist/tokens/colors.js +0 -34
- package/node_modules/@poe-code/design-system/package.json +0 -29
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/theme.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.js +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, randomBytes, scrypt } from "node:crypto";
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes, randomUUID, scrypt } from "node:crypto";
|
|
2
2
|
import { promises as fs } from "node:fs";
|
|
3
3
|
import { homedir, hostname, userInfo } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { hasOwnErrorCode } from "./error-codes.js";
|
|
5
6
|
const derivedKeyCache = new Map();
|
|
6
7
|
const ENCRYPTION_ALGORITHM = "aes-256-gcm";
|
|
7
8
|
const ENCRYPTION_VERSION = 1;
|
|
@@ -9,7 +10,6 @@ const ENCRYPTION_KEY_BYTES = 32;
|
|
|
9
10
|
const ENCRYPTION_IV_BYTES = 12;
|
|
10
11
|
const ENCRYPTION_AUTH_TAG_BYTES = 16;
|
|
11
12
|
const ENCRYPTION_FILE_MODE = 0o600;
|
|
12
|
-
let temporaryFileSequence = 0;
|
|
13
13
|
export class EncryptedFileStore {
|
|
14
14
|
fs;
|
|
15
15
|
filePath;
|
|
@@ -35,7 +35,7 @@ export class EncryptedFileStore {
|
|
|
35
35
|
this.getRandomBytes = input.getRandomBytes ?? randomBytes;
|
|
36
36
|
}
|
|
37
37
|
async get() {
|
|
38
|
-
await this.
|
|
38
|
+
await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
|
|
39
39
|
let rawDocument;
|
|
40
40
|
try {
|
|
41
41
|
rawDocument = await this.fs.readFile(this.filePath, "utf8");
|
|
@@ -69,7 +69,7 @@ export class EncryptedFileStore {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
async set(value) {
|
|
72
|
-
await this.
|
|
72
|
+
await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
|
|
73
73
|
const key = await this.getEncryptionKey();
|
|
74
74
|
const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);
|
|
75
75
|
const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
|
|
@@ -85,26 +85,29 @@ export class EncryptedFileStore {
|
|
|
85
85
|
ciphertext: ciphertext.toString("base64")
|
|
86
86
|
};
|
|
87
87
|
await this.fs.mkdir(path.dirname(this.filePath), { recursive: true });
|
|
88
|
-
await this.
|
|
89
|
-
const temporaryPath = `${this.filePath}.${process.pid}.${
|
|
88
|
+
await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
|
|
89
|
+
const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
90
|
+
let temporaryCreated = false;
|
|
90
91
|
try {
|
|
92
|
+
await this.assertCredentialPathHasNoSymbolicLinks(temporaryPath);
|
|
91
93
|
await this.fs.writeFile(temporaryPath, JSON.stringify(document), {
|
|
92
94
|
encoding: "utf8",
|
|
93
95
|
flag: "wx",
|
|
94
96
|
mode: ENCRYPTION_FILE_MODE
|
|
95
97
|
});
|
|
98
|
+
temporaryCreated = true;
|
|
96
99
|
await this.fs.chmod(temporaryPath, ENCRYPTION_FILE_MODE);
|
|
97
100
|
await this.fs.rename(temporaryPath, this.filePath);
|
|
98
101
|
}
|
|
99
102
|
catch (error) {
|
|
100
|
-
if (!isAlreadyExistsError(error)) {
|
|
103
|
+
if (temporaryCreated || !isAlreadyExistsError(error)) {
|
|
101
104
|
await removeIfPresent(this.fs, temporaryPath).catch(() => undefined);
|
|
102
105
|
}
|
|
103
106
|
throw error;
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
async delete() {
|
|
107
|
-
await this.
|
|
110
|
+
await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);
|
|
108
111
|
try {
|
|
109
112
|
await this.fs.unlink(this.filePath);
|
|
110
113
|
}
|
|
@@ -114,8 +117,8 @@ export class EncryptedFileStore {
|
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
|
-
async
|
|
118
|
-
const resolvedPath = path.resolve(
|
|
120
|
+
async assertCredentialPathHasNoSymbolicLinks(targetPath) {
|
|
121
|
+
const resolvedPath = path.resolve(targetPath);
|
|
119
122
|
const protectedPaths = getProtectedCredentialPaths(resolvedPath, this.symbolicLinkCheckStartPath);
|
|
120
123
|
for (const currentPath of protectedPaths) {
|
|
121
124
|
try {
|
|
@@ -179,12 +182,6 @@ async function removeIfPresent(fileSystem, filePath) {
|
|
|
179
182
|
}
|
|
180
183
|
}
|
|
181
184
|
}
|
|
182
|
-
function isAlreadyExistsError(error) {
|
|
183
|
-
return (typeof error === "object" &&
|
|
184
|
-
error !== null &&
|
|
185
|
-
"code" in error &&
|
|
186
|
-
error.code === "EEXIST");
|
|
187
|
-
}
|
|
188
185
|
function defaultMachineIdentity() {
|
|
189
186
|
return {
|
|
190
187
|
hostname: hostname(),
|
|
@@ -222,19 +219,23 @@ function parseEncryptedDocument(raw) {
|
|
|
222
219
|
if (!isRecord(parsed)) {
|
|
223
220
|
return null;
|
|
224
221
|
}
|
|
225
|
-
|
|
222
|
+
const version = getOwnEntry(parsed, "version");
|
|
223
|
+
const iv = getOwnEntry(parsed, "iv");
|
|
224
|
+
const authTag = getOwnEntry(parsed, "authTag");
|
|
225
|
+
const ciphertext = getOwnEntry(parsed, "ciphertext");
|
|
226
|
+
if (version !== ENCRYPTION_VERSION) {
|
|
226
227
|
return null;
|
|
227
228
|
}
|
|
228
|
-
if (typeof
|
|
229
|
-
typeof
|
|
230
|
-
typeof
|
|
229
|
+
if (typeof iv !== "string" ||
|
|
230
|
+
typeof authTag !== "string" ||
|
|
231
|
+
typeof ciphertext !== "string") {
|
|
231
232
|
return null;
|
|
232
233
|
}
|
|
233
234
|
return {
|
|
234
|
-
version
|
|
235
|
-
iv
|
|
236
|
-
authTag
|
|
237
|
-
ciphertext
|
|
235
|
+
version,
|
|
236
|
+
iv,
|
|
237
|
+
authTag,
|
|
238
|
+
ciphertext
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
241
|
catch {
|
|
@@ -244,9 +245,12 @@ function parseEncryptedDocument(raw) {
|
|
|
244
245
|
function isRecord(value) {
|
|
245
246
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
246
247
|
}
|
|
248
|
+
function getOwnEntry(record, key) {
|
|
249
|
+
return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
250
|
+
}
|
|
247
251
|
function isNotFoundError(error) {
|
|
248
|
-
return
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
return hasOwnErrorCode(error, "ENOENT");
|
|
253
|
+
}
|
|
254
|
+
function isAlreadyExistsError(error) {
|
|
255
|
+
return hasOwnErrorCode(error, "EEXIST");
|
|
252
256
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hasOwnErrorCode(error: unknown, code: string): boolean;
|
|
@@ -12,8 +12,8 @@ export class KeychainStore {
|
|
|
12
12
|
}
|
|
13
13
|
async get() {
|
|
14
14
|
const result = await this.executeSecurityCommand(["find-generic-password", "-s", this.service, "-a", this.account, "-w"], "read secret from macOS Keychain");
|
|
15
|
-
if (result
|
|
16
|
-
return stripTrailingLineBreak(result
|
|
15
|
+
if (getCommandExitCode(result) === 0) {
|
|
16
|
+
return stripTrailingLineBreak(getCommandOutput(result, "stdout"));
|
|
17
17
|
}
|
|
18
18
|
if (isKeychainEntryNotFound(result)) {
|
|
19
19
|
return null;
|
|
@@ -33,13 +33,13 @@ export class KeychainStore {
|
|
|
33
33
|
"-U",
|
|
34
34
|
"-w"
|
|
35
35
|
], "store secret in macOS Keychain", { stdin: value });
|
|
36
|
-
if (result
|
|
36
|
+
if (getCommandExitCode(result) !== 0) {
|
|
37
37
|
throw createSecurityCliFailure("store secret in macOS Keychain", result);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
async delete() {
|
|
41
41
|
const result = await this.executeSecurityCommand(["delete-generic-password", "-s", this.service, "-a", this.account], "delete secret from macOS Keychain");
|
|
42
|
-
if (result
|
|
42
|
+
if (getCommandExitCode(result) === 0 || isKeychainEntryNotFound(result)) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
throw createSecurityCliFailure("delete secret from macOS Keychain", result);
|
|
@@ -121,12 +121,27 @@ function stripTrailingLineBreak(value) {
|
|
|
121
121
|
return value;
|
|
122
122
|
}
|
|
123
123
|
function isKeychainEntryNotFound(result) {
|
|
124
|
-
return result
|
|
124
|
+
return getCommandExitCode(result) === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;
|
|
125
125
|
}
|
|
126
126
|
function createSecurityCliFailure(operation, result) {
|
|
127
|
-
const
|
|
127
|
+
const exitCode = getCommandExitCode(result);
|
|
128
|
+
const details = getCommandOutput(result, "stderr").trim()
|
|
129
|
+
|| getCommandOutput(result, "stdout").trim();
|
|
128
130
|
if (details) {
|
|
129
|
-
return new Error(`Failed to ${operation}: security exited with code ${
|
|
131
|
+
return new Error(`Failed to ${operation}: security exited with code ${exitCode}: ${details}`);
|
|
130
132
|
}
|
|
131
|
-
return new Error(`Failed to ${operation}: security exited with code ${
|
|
133
|
+
return new Error(`Failed to ${operation}: security exited with code ${exitCode}`);
|
|
134
|
+
}
|
|
135
|
+
function getCommandExitCode(result) {
|
|
136
|
+
const value = getOwnEntry(result, "exitCode");
|
|
137
|
+
return typeof value === "number" && Number.isInteger(value) ? value : 1;
|
|
138
|
+
}
|
|
139
|
+
function getCommandOutput(result, key) {
|
|
140
|
+
const value = getOwnEntry(result, key);
|
|
141
|
+
return typeof value === "string" ? value : "";
|
|
142
|
+
}
|
|
143
|
+
function getOwnEntry(record, key) {
|
|
144
|
+
return Object.prototype.hasOwnProperty.call(record, key)
|
|
145
|
+
? record[key]
|
|
146
|
+
: undefined;
|
|
132
147
|
}
|
|
@@ -41,11 +41,13 @@ export function createAuthStoreClientStore(options) {
|
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
43
|
const parsed = JSON.parse(value);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
&&
|
|
48
|
-
|
|
44
|
+
const clientId = isObjectRecord(parsed) ? getOwnString(parsed, "clientId") : undefined;
|
|
45
|
+
if (clientId !== undefined) {
|
|
46
|
+
const client = { clientId };
|
|
47
|
+
if (isObjectRecord(parsed) && Object.prototype.hasOwnProperty.call(parsed, "clientSecret")) {
|
|
48
|
+
client.clientSecret = getOwnEntry(parsed, "clientSecret");
|
|
49
|
+
}
|
|
50
|
+
return client;
|
|
49
51
|
}
|
|
50
52
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
51
53
|
},
|
|
@@ -98,3 +100,13 @@ function createIssuerSecretStore(issuer, options) {
|
|
|
98
100
|
accountPrefix: "issuer",
|
|
99
101
|
});
|
|
100
102
|
}
|
|
103
|
+
function isObjectRecord(value) {
|
|
104
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
105
|
+
}
|
|
106
|
+
function getOwnEntry(record, key) {
|
|
107
|
+
return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
108
|
+
}
|
|
109
|
+
function getOwnString(record, key) {
|
|
110
|
+
const value = getOwnEntry(record, key);
|
|
111
|
+
return typeof value === "string" ? value : undefined;
|
|
112
|
+
}
|
|
@@ -15,20 +15,33 @@ export function parseAuthorizationState(value) {
|
|
|
15
15
|
try {
|
|
16
16
|
const decoded = Buffer.from(value, "base64url").toString("utf8");
|
|
17
17
|
const parsed = JSON.parse(decoded);
|
|
18
|
-
if (parsed
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
if (!isObjectRecord(parsed)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const version = getOwnEntry(parsed, "v");
|
|
22
|
+
const nonce = getOwnEntry(parsed, "n");
|
|
23
|
+
const issuer = getOwnEntry(parsed, "i");
|
|
24
|
+
const requireIssuer = getOwnEntry(parsed, "r");
|
|
25
|
+
if (version !== 1
|
|
26
|
+
|| typeof nonce !== "string"
|
|
27
|
+
|| nonce.length === 0
|
|
28
|
+
|| typeof issuer !== "string"
|
|
29
|
+
|| issuer.length === 0
|
|
30
|
+
|| typeof requireIssuer !== "boolean") {
|
|
24
31
|
return null;
|
|
25
32
|
}
|
|
26
33
|
return {
|
|
27
|
-
issuer
|
|
28
|
-
requireIssuer
|
|
34
|
+
issuer,
|
|
35
|
+
requireIssuer,
|
|
29
36
|
};
|
|
30
37
|
}
|
|
31
38
|
catch {
|
|
32
39
|
return null;
|
|
33
40
|
}
|
|
34
41
|
}
|
|
42
|
+
function isObjectRecord(value) {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
function getOwnEntry(record, key) {
|
|
46
|
+
return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
47
|
+
}
|
|
@@ -98,7 +98,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
98
98
|
while (true) {
|
|
99
99
|
try {
|
|
100
100
|
refreshedTokens = await refreshAccessToken({
|
|
101
|
-
tokenEndpoint: discovery.authorizationServerMetadata
|
|
101
|
+
tokenEndpoint: requireOwnString(discovery.authorizationServerMetadata, "token_endpoint", "Authorization server metadata"),
|
|
102
102
|
clientId: session.client.clientId,
|
|
103
103
|
clientSecret: session.client.clientSecret,
|
|
104
104
|
refreshToken: session.tokens.refreshToken,
|
|
@@ -184,7 +184,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
184
184
|
});
|
|
185
185
|
const code = await loopback.waitForCode(authorizationUrl);
|
|
186
186
|
const tokens = await exchangeAuthorizationCode({
|
|
187
|
-
tokenEndpoint: discovery.authorizationServerMetadata
|
|
187
|
+
tokenEndpoint: requireOwnString(discovery.authorizationServerMetadata, "token_endpoint", "Authorization server metadata"),
|
|
188
188
|
clientId: resolvedClient.client.clientId,
|
|
189
189
|
clientSecret: resolvedClient.client.clientSecret,
|
|
190
190
|
code,
|
|
@@ -239,7 +239,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
239
239
|
},
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
|
-
const registrationEndpoint = discovery.authorizationServerMetadata
|
|
242
|
+
const registrationEndpoint = getOwnString(discovery.authorizationServerMetadata, "registration_endpoint");
|
|
243
243
|
if (registrationEndpoint === undefined && options.client.clientId !== undefined) {
|
|
244
244
|
return {
|
|
245
245
|
kind: "static",
|
|
@@ -290,14 +290,16 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
290
290
|
body: JSON.stringify(registrationBody),
|
|
291
291
|
});
|
|
292
292
|
const payload = await readOAuthJsonObjectResponse(response);
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
const clientId = getOwnString(payload, "client_id");
|
|
294
|
+
if (clientId === undefined ||
|
|
295
|
+
clientId.trim().length === 0) {
|
|
295
296
|
throw new Error("OAuth client registration response missing client_id");
|
|
296
297
|
}
|
|
298
|
+
const clientSecret = getOwnString(payload, "client_secret");
|
|
297
299
|
const registeredClient = {
|
|
298
|
-
clientId
|
|
299
|
-
clientSecret:
|
|
300
|
-
?
|
|
300
|
+
clientId,
|
|
301
|
+
clientSecret: clientSecret !== undefined && clientSecret.length > 0
|
|
302
|
+
? clientSecret
|
|
301
303
|
: undefined,
|
|
302
304
|
};
|
|
303
305
|
await saveRegisteredClient(discovery.authorizationServer, registeredClient);
|
|
@@ -324,12 +326,13 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
324
326
|
return null;
|
|
325
327
|
}
|
|
326
328
|
const client = await clientStore.load(issuer);
|
|
327
|
-
|
|
329
|
+
const normalizedClient = client === null ? null : normalizeStoredClient(client);
|
|
330
|
+
if (client !== null && normalizedClient === null) {
|
|
328
331
|
await clientStore.clear(issuer);
|
|
329
332
|
return null;
|
|
330
333
|
}
|
|
331
|
-
registeredClients.set(issuer,
|
|
332
|
-
return
|
|
334
|
+
registeredClients.set(issuer, normalizedClient);
|
|
335
|
+
return normalizedClient;
|
|
333
336
|
}
|
|
334
337
|
async function saveRegisteredClient(issuer, client) {
|
|
335
338
|
registeredClients.set(issuer, client);
|
|
@@ -345,7 +348,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
345
348
|
}
|
|
346
349
|
}
|
|
347
350
|
function isProviderOptions(options) {
|
|
348
|
-
return "provider"
|
|
351
|
+
return Object.prototype.hasOwnProperty.call(options, "provider");
|
|
349
352
|
}
|
|
350
353
|
function isExpired(tokens, now) {
|
|
351
354
|
return tokens.expiresAt !== null && tokens.expiresAt <= now();
|
|
@@ -361,11 +364,15 @@ function resolveDiscovery(discovery, session) {
|
|
|
361
364
|
return undefined;
|
|
362
365
|
}
|
|
363
366
|
const metadata = session.discovery.authorizationServerMetadata;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
const issuer = getOwnString(metadata, "issuer");
|
|
368
|
+
const authorizationEndpoint = getOwnString(metadata, "authorization_endpoint");
|
|
369
|
+
const tokenEndpoint = getOwnString(metadata, "token_endpoint");
|
|
370
|
+
const codeChallengeMethodsSupported = getOwnStringArray(metadata, "code_challenge_methods_supported");
|
|
371
|
+
if (issuer === undefined ||
|
|
372
|
+
authorizationEndpoint === undefined ||
|
|
373
|
+
tokenEndpoint === undefined ||
|
|
374
|
+
codeChallengeMethodsSupported === undefined ||
|
|
375
|
+
!codeChallengeMethodsSupported.includes("S256")) {
|
|
369
376
|
return undefined;
|
|
370
377
|
}
|
|
371
378
|
return {
|
|
@@ -389,39 +396,96 @@ function normalizeLoadedSession(session) {
|
|
|
389
396
|
if (session === null) {
|
|
390
397
|
return null;
|
|
391
398
|
}
|
|
392
|
-
|
|
399
|
+
const client = normalizeStoredClient(getOwnEntry(session, "client"));
|
|
400
|
+
if (client === null) {
|
|
393
401
|
return { ...session, client: { clientId: "" }, tokens: undefined };
|
|
394
402
|
}
|
|
395
|
-
return
|
|
396
|
-
|
|
397
|
-
|
|
403
|
+
return {
|
|
404
|
+
...session,
|
|
405
|
+
client,
|
|
406
|
+
tokens: normalizeStoredTokens(getOwnEntry(session, "tokens")),
|
|
407
|
+
};
|
|
398
408
|
}
|
|
399
|
-
function
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
409
|
+
function normalizeStoredClient(value) {
|
|
410
|
+
if (!isObjectRecord(value)) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
const clientId = getOwnString(value, "clientId");
|
|
414
|
+
if (clientId === undefined || clientId.trim().length === 0) {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
const clientSecret = getOwnEntry(value, "clientSecret");
|
|
418
|
+
if (clientSecret === undefined) {
|
|
419
|
+
return { clientId };
|
|
420
|
+
}
|
|
421
|
+
if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
return { clientId, clientSecret };
|
|
404
425
|
}
|
|
405
|
-
function
|
|
406
|
-
if (
|
|
407
|
-
return
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
426
|
+
function normalizeStoredTokens(value) {
|
|
427
|
+
if (value === undefined || !isObjectRecord(value)) {
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
430
|
+
const accessToken = getOwnString(value, "accessToken");
|
|
431
|
+
const tokenType = getOwnString(value, "tokenType");
|
|
432
|
+
const expiresAt = getOwnEntry(value, "expiresAt");
|
|
433
|
+
const refreshToken = getOwnEntry(value, "refreshToken");
|
|
434
|
+
const scope = getOwnString(value, "scope");
|
|
435
|
+
const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken : undefined;
|
|
436
|
+
if (accessToken === undefined ||
|
|
437
|
+
accessToken.trim().length === 0 ||
|
|
438
|
+
tokenType !== "Bearer" ||
|
|
439
|
+
!(expiresAt === null ||
|
|
440
|
+
(typeof expiresAt === "number" && Number.isFinite(expiresAt))) ||
|
|
441
|
+
(refreshToken !== undefined &&
|
|
442
|
+
(typeof refreshToken !== "string" || refreshToken.trim().length === 0))) {
|
|
443
|
+
return undefined;
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
accessToken,
|
|
447
|
+
tokenType,
|
|
448
|
+
expiresAt,
|
|
449
|
+
...(normalizedRefreshToken === undefined ? {} : { refreshToken: normalizedRefreshToken }),
|
|
450
|
+
...(scope === undefined || scope.length === 0 ? {} : { scope }),
|
|
451
|
+
};
|
|
415
452
|
}
|
|
416
453
|
function getClientMetadata(client) {
|
|
417
454
|
return client.metadata;
|
|
418
455
|
}
|
|
456
|
+
function getOwnEntry(record, key) {
|
|
457
|
+
return Object.prototype.hasOwnProperty.call(record, key)
|
|
458
|
+
? record[key]
|
|
459
|
+
: undefined;
|
|
460
|
+
}
|
|
461
|
+
function isObjectRecord(value) {
|
|
462
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
463
|
+
}
|
|
464
|
+
function getOwnString(record, key) {
|
|
465
|
+
const value = getOwnEntry(record, key);
|
|
466
|
+
return typeof value === "string" ? value : undefined;
|
|
467
|
+
}
|
|
468
|
+
function requireOwnString(record, key, label) {
|
|
469
|
+
const value = getOwnString(record, key);
|
|
470
|
+
if (value === undefined) {
|
|
471
|
+
throw new Error(`${label} is missing ${key}`);
|
|
472
|
+
}
|
|
473
|
+
return value;
|
|
474
|
+
}
|
|
475
|
+
function getOwnStringArray(record, key) {
|
|
476
|
+
const value = getOwnEntry(record, key);
|
|
477
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string")
|
|
478
|
+
? value
|
|
479
|
+
: undefined;
|
|
480
|
+
}
|
|
419
481
|
function buildAuthorizationUrl(input) {
|
|
420
|
-
const
|
|
482
|
+
const authorizationEndpoint = requireOwnString(input.metadata, "authorization_endpoint", "Authorization server metadata");
|
|
483
|
+
const issuer = requireOwnString(input.metadata, "issuer", "Authorization server metadata");
|
|
484
|
+
const url = new URL(authorizationEndpoint);
|
|
421
485
|
const resource = canonicalizeResourceIndicator(input.resource);
|
|
422
486
|
const state = createAuthorizationState({
|
|
423
|
-
issuer
|
|
424
|
-
requireIssuer: input.metadata
|
|
487
|
+
issuer,
|
|
488
|
+
requireIssuer: getOwnEntry(input.metadata, "authorization_response_iss_parameter_supported") === true,
|
|
425
489
|
});
|
|
426
490
|
url.searchParams.set("response_type", "code");
|
|
427
491
|
url.searchParams.set("client_id", input.clientId);
|
|
@@ -436,7 +500,7 @@ function buildAuthorizationUrl(input) {
|
|
|
436
500
|
return url.toString();
|
|
437
501
|
}
|
|
438
502
|
function assertS256PkceSupport(metadata) {
|
|
439
|
-
if (!metadata
|
|
503
|
+
if (!getOwnStringArray(metadata, "code_challenge_methods_supported")?.includes("S256")) {
|
|
440
504
|
throw new Error("Authorization server metadata must advertise code_challenge_methods_supported including S256");
|
|
441
505
|
}
|
|
442
506
|
}
|
|
@@ -460,13 +524,16 @@ function assertSecureUrl(value, label) {
|
|
|
460
524
|
throw new Error(`${label} must use https unless it targets a loopback host`);
|
|
461
525
|
}
|
|
462
526
|
function assertSecureOAuthFlowEndpoints(metadata) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
527
|
+
const authorizationEndpoint = requireOwnString(metadata, "authorization_endpoint", "Authorization server metadata");
|
|
528
|
+
const tokenEndpoint = requireOwnString(metadata, "token_endpoint", "Authorization server metadata");
|
|
529
|
+
const registrationEndpoint = getOwnString(metadata, "registration_endpoint");
|
|
530
|
+
assertNoAccessTokenInUrl(authorizationEndpoint, "Authorization endpoint");
|
|
531
|
+
assertNoAccessTokenInUrl(tokenEndpoint, "Token endpoint");
|
|
532
|
+
assertSecureUrl(authorizationEndpoint, "Authorization endpoint");
|
|
533
|
+
assertSecureUrl(tokenEndpoint, "Token endpoint");
|
|
534
|
+
if (registrationEndpoint !== undefined) {
|
|
535
|
+
assertNoAccessTokenInUrl(registrationEndpoint, "Registration endpoint");
|
|
536
|
+
assertSecureUrl(registrationEndpoint, "Registration endpoint");
|
|
470
537
|
}
|
|
471
538
|
}
|
|
472
539
|
function assertNoAccessTokenInUrl(value, label) {
|
|
@@ -487,17 +554,23 @@ function buildClientRegistrationBody(metadata, redirectUri) {
|
|
|
487
554
|
response_types: ["code"],
|
|
488
555
|
token_endpoint_auth_method: "none",
|
|
489
556
|
};
|
|
490
|
-
|
|
491
|
-
|
|
557
|
+
const clientName = metadata === undefined ? undefined : getOwnString(metadata, "clientName");
|
|
558
|
+
const scope = metadata === undefined ? undefined : getOwnString(metadata, "scope");
|
|
559
|
+
const softwareId = metadata === undefined ? undefined : getOwnString(metadata, "softwareId");
|
|
560
|
+
const softwareVersion = metadata === undefined
|
|
561
|
+
? undefined
|
|
562
|
+
: getOwnString(metadata, "softwareVersion");
|
|
563
|
+
if (clientName !== undefined && clientName.length > 0) {
|
|
564
|
+
body.client_name = clientName;
|
|
492
565
|
}
|
|
493
|
-
if (
|
|
494
|
-
body.scope =
|
|
566
|
+
if (scope !== undefined && scope.length > 0) {
|
|
567
|
+
body.scope = scope;
|
|
495
568
|
}
|
|
496
|
-
if (
|
|
497
|
-
body.software_id =
|
|
569
|
+
if (softwareId !== undefined && softwareId.length > 0) {
|
|
570
|
+
body.software_id = softwareId;
|
|
498
571
|
}
|
|
499
|
-
if (
|
|
500
|
-
body.software_version =
|
|
572
|
+
if (softwareVersion !== undefined && softwareVersion.length > 0) {
|
|
573
|
+
body.software_version = softwareVersion;
|
|
501
574
|
}
|
|
502
575
|
return body;
|
|
503
576
|
}
|
|
@@ -75,29 +75,33 @@ async function requestTokens(input) {
|
|
|
75
75
|
body: body.toString(),
|
|
76
76
|
});
|
|
77
77
|
const payload = await readOAuthJsonObjectResponse(response);
|
|
78
|
-
|
|
78
|
+
const accessToken = getOwnEntry(payload, "access_token");
|
|
79
|
+
if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
|
|
79
80
|
throw new Error("OAuth token response missing access_token");
|
|
80
81
|
}
|
|
81
|
-
const tokenType = normalizeBearerTokenType(payload
|
|
82
|
+
const tokenType = normalizeBearerTokenType(getOwnEntry(payload, "token_type"));
|
|
82
83
|
if (tokenType === null) {
|
|
83
84
|
throw new Error("OAuth token response missing token_type=Bearer");
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
&&
|
|
86
|
+
const expiresIn = getOwnEntry(payload, "expires_in");
|
|
87
|
+
if (typeof expiresIn === "number"
|
|
88
|
+
&& Number.isFinite(expiresIn)
|
|
89
|
+
&& expiresIn < 0) {
|
|
88
90
|
throw new Error("OAuth token response has invalid expires_in");
|
|
89
91
|
}
|
|
92
|
+
const refreshToken = getOwnEntry(payload, "refresh_token");
|
|
93
|
+
const scope = getOwnEntry(payload, "scope");
|
|
90
94
|
return {
|
|
91
|
-
accessToken
|
|
92
|
-
refreshToken: typeof
|
|
93
|
-
?
|
|
95
|
+
accessToken,
|
|
96
|
+
refreshToken: typeof refreshToken === "string" && refreshToken.length > 0
|
|
97
|
+
? refreshToken
|
|
94
98
|
: undefined,
|
|
95
99
|
tokenType,
|
|
96
|
-
expiresAt: typeof
|
|
97
|
-
? input.now() + (
|
|
100
|
+
expiresAt: typeof expiresIn === "number" && Number.isFinite(expiresIn)
|
|
101
|
+
? input.now() + (expiresIn * 1000)
|
|
98
102
|
: null,
|
|
99
|
-
scope: typeof
|
|
100
|
-
?
|
|
103
|
+
scope: typeof scope === "string" && scope.length > 0
|
|
104
|
+
? scope
|
|
101
105
|
: undefined,
|
|
102
106
|
};
|
|
103
107
|
}
|
|
@@ -126,16 +130,22 @@ export async function readOAuthJsonObjectResponse(response) {
|
|
|
126
130
|
return record;
|
|
127
131
|
}
|
|
128
132
|
function readOAuthError(payload, fallbackError = "server_error") {
|
|
133
|
+
const error = getOwnEntry(payload, "error");
|
|
134
|
+
const errorDescription = getOwnEntry(payload, "error_description");
|
|
135
|
+
const errorUri = getOwnEntry(payload, "error_uri");
|
|
129
136
|
return {
|
|
130
|
-
error: typeof
|
|
131
|
-
error_description: typeof
|
|
132
|
-
?
|
|
137
|
+
error: typeof error === "string" ? error : fallbackError,
|
|
138
|
+
error_description: typeof errorDescription === "string"
|
|
139
|
+
? errorDescription
|
|
133
140
|
: undefined,
|
|
134
|
-
error_uri: typeof
|
|
135
|
-
?
|
|
141
|
+
error_uri: typeof errorUri === "string"
|
|
142
|
+
? errorUri
|
|
136
143
|
: undefined,
|
|
137
144
|
};
|
|
138
145
|
}
|
|
146
|
+
function getOwnEntry(record, key) {
|
|
147
|
+
return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
148
|
+
}
|
|
139
149
|
function createFallbackOAuthError(status) {
|
|
140
150
|
const error = status === 503 ? "temporarily_unavailable" : "server_error";
|
|
141
151
|
return new OAuthError({ error }, status);
|