@antseed/cli 0.1.179 → 0.1.181
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 +5 -3
- package/dist/buyer-identities/store.d.ts +39 -2
- package/dist/buyer-identities/store.d.ts.map +1 -1
- package/dist/buyer-identities/store.js +99 -10
- package/dist/buyer-identities/store.js.map +1 -1
- package/dist/cli/commands/apps/index.js +8 -8
- package/dist/cli/commands/buyer/identity.d.ts +3 -1
- package/dist/cli/commands/buyer/identity.d.ts.map +1 -1
- package/dist/cli/commands/buyer/identity.js +55 -8
- package/dist/cli/commands/buyer/identity.js.map +1 -1
- package/dist/cli/commands/buyer/identity.test.d.ts +2 -0
- package/dist/cli/commands/buyer/identity.test.d.ts.map +1 -0
- package/dist/cli/commands/buyer/identity.test.js +168 -0
- package/dist/cli/commands/buyer/identity.test.js.map +1 -0
- package/dist/cli/commands/buyer/set-authorized-wallet.d.ts +10 -0
- package/dist/cli/commands/buyer/set-authorized-wallet.d.ts.map +1 -1
- package/dist/cli/commands/buyer/set-authorized-wallet.js +26 -4
- package/dist/cli/commands/buyer/set-authorized-wallet.js.map +1 -1
- package/dist/cli/commands/buyer/set-authorized-wallet.test.js +37 -2
- package/dist/cli/commands/buyer/set-authorized-wallet.test.js.map +1 -1
- package/dist/cli/commands/buyer/start.d.ts +15 -0
- package/dist/cli/commands/buyer/start.d.ts.map +1 -1
- package/dist/cli/commands/buyer/start.js +158 -49
- package/dist/cli/commands/buyer/start.js.map +1 -1
- package/dist/cli/commands/buyer/start.test.js +16 -1
- package/dist/cli/commands/buyer/start.test.js.map +1 -1
- package/dist/cli/commands/chat.d.ts +3 -0
- package/dist/cli/commands/chat.d.ts.map +1 -0
- package/dist/cli/commands/chat.js +189 -0
- package/dist/cli/commands/chat.js.map +1 -0
- package/dist/cli/commands/gateway/activity.d.ts +15 -0
- package/dist/cli/commands/gateway/activity.d.ts.map +1 -0
- package/dist/cli/commands/gateway/activity.js +233 -0
- package/dist/cli/commands/gateway/activity.js.map +1 -0
- package/dist/cli/commands/gateway/admin-token.d.ts +3 -0
- package/dist/cli/commands/gateway/admin-token.d.ts.map +1 -0
- package/dist/cli/commands/gateway/admin-token.js +90 -0
- package/dist/cli/commands/gateway/admin-token.js.map +1 -0
- package/dist/cli/commands/gateway/console-link.d.ts +20 -0
- package/dist/cli/commands/gateway/console-link.d.ts.map +1 -0
- package/dist/cli/commands/gateway/console-link.js +92 -0
- package/dist/cli/commands/gateway/console-link.js.map +1 -0
- package/dist/cli/commands/gateway/gateway-commands.test.d.ts +2 -0
- package/dist/cli/commands/gateway/gateway-commands.test.d.ts.map +1 -0
- package/dist/cli/commands/gateway/gateway-commands.test.js +230 -0
- package/dist/cli/commands/gateway/gateway-commands.test.js.map +1 -0
- package/dist/cli/commands/gateway/gateway-console-commands.test.d.ts +2 -0
- package/dist/cli/commands/gateway/gateway-console-commands.test.d.ts.map +1 -0
- package/dist/cli/commands/gateway/gateway-console-commands.test.js +373 -0
- package/dist/cli/commands/gateway/gateway-console-commands.test.js.map +1 -0
- package/dist/cli/commands/gateway/index.d.ts +8 -0
- package/dist/cli/commands/gateway/index.d.ts.map +1 -1
- package/dist/cli/commands/gateway/index.js +93 -14
- package/dist/cli/commands/gateway/index.js.map +1 -1
- package/dist/cli/commands/gateway/key.d.ts +4 -0
- package/dist/cli/commands/gateway/key.d.ts.map +1 -1
- package/dist/cli/commands/gateway/key.js +297 -182
- package/dist/cli/commands/gateway/key.js.map +1 -1
- package/dist/cli/commands/gateway/member.d.ts +3 -0
- package/dist/cli/commands/gateway/member.d.ts.map +1 -0
- package/dist/cli/commands/gateway/member.js +302 -0
- package/dist/cli/commands/gateway/member.js.map +1 -0
- package/dist/cli/commands/gateway/migrate.d.ts +18 -0
- package/dist/cli/commands/gateway/migrate.d.ts.map +1 -0
- package/dist/cli/commands/gateway/migrate.js +158 -0
- package/dist/cli/commands/gateway/migrate.js.map +1 -0
- package/dist/cli/commands/gateway/operator.d.ts +11 -0
- package/dist/cli/commands/gateway/operator.d.ts.map +1 -0
- package/dist/cli/commands/gateway/operator.js +199 -0
- package/dist/cli/commands/gateway/operator.js.map +1 -0
- package/dist/cli/commands/gateway/operator.test.d.ts +2 -0
- package/dist/cli/commands/gateway/operator.test.d.ts.map +1 -0
- package/dist/cli/commands/gateway/operator.test.js +151 -0
- package/dist/cli/commands/gateway/operator.test.js.map +1 -0
- package/dist/cli/commands/gateway/peer-list.d.ts +3 -0
- package/dist/cli/commands/gateway/peer-list.d.ts.map +1 -0
- package/dist/cli/commands/gateway/peer-list.js +107 -0
- package/dist/cli/commands/gateway/peer-list.js.map +1 -0
- package/dist/cli/commands/gateway/policy-options.d.ts +23 -0
- package/dist/cli/commands/gateway/policy-options.d.ts.map +1 -0
- package/dist/cli/commands/gateway/policy-options.js +156 -0
- package/dist/cli/commands/gateway/policy-options.js.map +1 -0
- package/dist/cli/commands/gateway/preset.d.ts +3 -0
- package/dist/cli/commands/gateway/preset.d.ts.map +1 -0
- package/dist/cli/commands/gateway/preset.js +181 -0
- package/dist/cli/commands/gateway/preset.js.map +1 -0
- package/dist/cli/commands/gateway/routing.d.ts +3 -0
- package/dist/cli/commands/gateway/routing.d.ts.map +1 -0
- package/dist/cli/commands/gateway/routing.js +110 -0
- package/dist/cli/commands/gateway/routing.js.map +1 -0
- package/dist/cli/commands/gateway/settings.d.ts +4 -0
- package/dist/cli/commands/gateway/settings.d.ts.map +1 -0
- package/dist/cli/commands/gateway/settings.js +314 -0
- package/dist/cli/commands/gateway/settings.js.map +1 -0
- package/dist/cli/commands/gateway/shared.d.ts +55 -6
- package/dist/cli/commands/gateway/shared.d.ts.map +1 -1
- package/dist/cli/commands/gateway/shared.js +206 -26
- package/dist/cli/commands/gateway/shared.js.map +1 -1
- package/dist/cli/commands/gateway/workspace.d.ts +3 -0
- package/dist/cli/commands/gateway/workspace.d.ts.map +1 -0
- package/dist/cli/commands/gateway/workspace.js +250 -0
- package/dist/cli/commands/gateway/workspace.js.map +1 -0
- package/dist/cli/commands/network/bootstrap.js +1 -1
- package/dist/cli/commands/seller/setup.js +1 -1
- package/dist/cli/commands/seller/start.d.ts.map +1 -1
- package/dist/cli/commands/seller/start.js +1 -2
- package/dist/cli/commands/seller/start.js.map +1 -1
- package/dist/cli/commands/system-proxy/index.js +1 -1
- package/dist/cli/commands/tunnel/start.d.ts.map +1 -1
- package/dist/cli/commands/tunnel/start.js +23 -5
- package/dist/cli/commands/tunnel/start.js.map +1 -1
- package/dist/cli/commands/wrapped-tools.js +8 -8
- package/dist/cli/commands/wrapped-tools.test.js +5 -5
- package/dist/cli/index.js +12 -44
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/program.d.ts +4 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +49 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/program.test.d.ts +2 -0
- package/dist/cli/program.test.d.ts.map +1 -0
- package/dist/cli/program.test.js +38 -0
- package/dist/cli/program.test.js.map +1 -0
- package/dist/cli/prompt-hidden.d.ts +3 -0
- package/dist/cli/prompt-hidden.d.ts.map +1 -0
- package/dist/cli/prompt-hidden.js +38 -0
- package/dist/cli/prompt-hidden.js.map +1 -0
- package/dist/cli/wallet-passphrase.d.ts +48 -0
- package/dist/cli/wallet-passphrase.d.ts.map +1 -0
- package/dist/cli/wallet-passphrase.js +119 -0
- package/dist/cli/wallet-passphrase.js.map +1 -0
- package/dist/cli/wallet-passphrase.test.d.ts +2 -0
- package/dist/cli/wallet-passphrase.test.d.ts.map +1 -0
- package/dist/cli/wallet-passphrase.test.js +79 -0
- package/dist/cli/wallet-passphrase.test.js.map +1 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +0 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/effective.d.ts +12 -0
- package/dist/config/effective.d.ts.map +1 -1
- package/dist/config/effective.js +39 -6
- package/dist/config/effective.js.map +1 -1
- package/dist/config/effective.test.js +9 -1
- package/dist/config/effective.test.js.map +1 -1
- package/dist/config/loader.d.ts +6 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +12 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/loader.test.js +7 -1
- package/dist/config/loader.test.js.map +1 -1
- package/dist/config/types.d.ts +14 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +19 -0
- package/dist/config/validation.js.map +1 -1
- package/dist/gateway/accounting.d.ts +33 -3
- package/dist/gateway/accounting.d.ts.map +1 -1
- package/dist/gateway/accounting.js +86 -7
- package/dist/gateway/accounting.js.map +1 -1
- package/dist/gateway/admission-benchmark.test.d.ts +2 -0
- package/dist/gateway/admission-benchmark.test.d.ts.map +1 -0
- package/dist/gateway/admission-benchmark.test.js +75 -0
- package/dist/gateway/admission-benchmark.test.js.map +1 -0
- package/dist/gateway/auth/auth.test.d.ts +4 -0
- package/dist/gateway/auth/auth.test.d.ts.map +1 -0
- package/dist/gateway/auth/auth.test.js +337 -0
- package/dist/gateway/auth/auth.test.js.map +1 -0
- package/dist/gateway/auth/credentials.test.d.ts +2 -0
- package/dist/gateway/auth/credentials.test.d.ts.map +1 -0
- package/dist/gateway/auth/credentials.test.js +132 -0
- package/dist/gateway/auth/credentials.test.js.map +1 -0
- package/dist/gateway/auth/db.d.ts +156 -0
- package/dist/gateway/auth/db.d.ts.map +1 -0
- package/dist/gateway/auth/db.js +390 -0
- package/dist/gateway/auth/db.js.map +1 -0
- package/dist/gateway/auth/hardening.test.d.ts +2 -0
- package/dist/gateway/auth/hardening.test.d.ts.map +1 -0
- package/dist/gateway/auth/hardening.test.js +155 -0
- package/dist/gateway/auth/hardening.test.js.map +1 -0
- package/dist/gateway/auth/http.d.ts +53 -0
- package/dist/gateway/auth/http.d.ts.map +1 -0
- package/dist/gateway/auth/http.js +165 -0
- package/dist/gateway/auth/http.js.map +1 -0
- package/dist/gateway/auth/index.d.ts +26 -0
- package/dist/gateway/auth/index.d.ts.map +1 -0
- package/dist/gateway/auth/index.js +1014 -0
- package/dist/gateway/auth/index.js.map +1 -0
- package/dist/gateway/auth/oidc.d.ts +57 -0
- package/dist/gateway/auth/oidc.d.ts.map +1 -0
- package/dist/gateway/auth/oidc.js +159 -0
- package/dist/gateway/auth/oidc.js.map +1 -0
- package/dist/gateway/auth/oidc.test.d.ts +2 -0
- package/dist/gateway/auth/oidc.test.d.ts.map +1 -0
- package/dist/gateway/auth/oidc.test.js +223 -0
- package/dist/gateway/auth/oidc.test.js.map +1 -0
- package/dist/gateway/auth/reauth.test.d.ts +2 -0
- package/dist/gateway/auth/reauth.test.d.ts.map +1 -0
- package/dist/gateway/auth/reauth.test.js +108 -0
- package/dist/gateway/auth/reauth.test.js.map +1 -0
- package/dist/gateway/auth/store-integration.test.d.ts +2 -0
- package/dist/gateway/auth/store-integration.test.d.ts.map +1 -0
- package/dist/gateway/auth/store-integration.test.js +100 -0
- package/dist/gateway/auth/store-integration.test.js.map +1 -0
- package/dist/gateway/auth/test-helpers.d.ts +167 -0
- package/dist/gateway/auth/test-helpers.d.ts.map +1 -0
- package/dist/gateway/auth/test-helpers.js +368 -0
- package/dist/gateway/auth/test-helpers.js.map +1 -0
- package/dist/gateway/auth/types.d.ts +145 -0
- package/dist/gateway/auth/types.d.ts.map +1 -0
- package/dist/gateway/auth/types.js +2 -0
- package/dist/gateway/auth/types.js.map +1 -0
- package/dist/gateway/auth/wallet.d.ts +15 -0
- package/dist/gateway/auth/wallet.d.ts.map +1 -0
- package/dist/gateway/auth/wallet.js +43 -0
- package/dist/gateway/auth/wallet.js.map +1 -0
- package/dist/gateway/bundle.d.ts +127 -0
- package/dist/gateway/bundle.d.ts.map +1 -0
- package/dist/gateway/bundle.js +604 -0
- package/dist/gateway/bundle.js.map +1 -0
- package/dist/gateway/bundle.test.d.ts +2 -0
- package/dist/gateway/bundle.test.d.ts.map +1 -0
- package/dist/gateway/bundle.test.js +277 -0
- package/dist/gateway/bundle.test.js.map +1 -0
- package/dist/gateway/buyer-control.d.ts +33 -0
- package/dist/gateway/buyer-control.d.ts.map +1 -0
- package/dist/gateway/buyer-control.js +93 -0
- package/dist/gateway/buyer-control.js.map +1 -0
- package/dist/gateway/buyer-policy-probe.d.ts +41 -0
- package/dist/gateway/buyer-policy-probe.d.ts.map +1 -0
- package/dist/gateway/buyer-policy-probe.js +99 -0
- package/dist/gateway/buyer-policy-probe.js.map +1 -0
- package/dist/gateway/buyer-policy-probe.test.d.ts +2 -0
- package/dist/gateway/buyer-policy-probe.test.d.ts.map +1 -0
- package/dist/gateway/buyer-policy-probe.test.js +128 -0
- package/dist/gateway/buyer-policy-probe.test.js.map +1 -0
- package/dist/gateway/buyer-process.d.ts +30 -0
- package/dist/gateway/buyer-process.d.ts.map +1 -0
- package/dist/gateway/buyer-process.js +101 -0
- package/dist/gateway/buyer-process.js.map +1 -0
- package/dist/gateway/buyer-process.test.d.ts +2 -0
- package/dist/gateway/buyer-process.test.d.ts.map +1 -0
- package/dist/gateway/buyer-process.test.js +112 -0
- package/dist/gateway/buyer-process.test.js.map +1 -0
- package/dist/gateway/chat/routes.d.ts +45 -0
- package/dist/gateway/chat/routes.d.ts.map +1 -0
- package/dist/gateway/chat/routes.js +439 -0
- package/dist/gateway/chat/routes.js.map +1 -0
- package/dist/gateway/chat/routes.test.d.ts +2 -0
- package/dist/gateway/chat/routes.test.d.ts.map +1 -0
- package/dist/gateway/chat/routes.test.js +304 -0
- package/dist/gateway/chat/routes.test.js.map +1 -0
- package/dist/gateway/chat/tools.d.ts +35 -0
- package/dist/gateway/chat/tools.d.ts.map +1 -0
- package/dist/gateway/chat/tools.js +347 -0
- package/dist/gateway/chat/tools.js.map +1 -0
- package/dist/gateway/chat/tools.test.d.ts +2 -0
- package/dist/gateway/chat/tools.test.d.ts.map +1 -0
- package/dist/gateway/chat/tools.test.js +136 -0
- package/dist/gateway/chat/tools.test.js.map +1 -0
- package/dist/gateway/console-api/access.d.ts +52 -0
- package/dist/gateway/console-api/access.d.ts.map +1 -0
- package/dist/gateway/console-api/access.js +171 -0
- package/dist/gateway/console-api/access.js.map +1 -0
- package/dist/gateway/console-api/deps.d.ts +52 -0
- package/dist/gateway/console-api/deps.d.ts.map +1 -0
- package/dist/gateway/console-api/deps.js +2 -0
- package/dist/gateway/console-api/deps.js.map +1 -0
- package/dist/gateway/console-api/handlers/admin-tokens.d.ts +8 -0
- package/dist/gateway/console-api/handlers/admin-tokens.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/admin-tokens.js +48 -0
- package/dist/gateway/console-api/handlers/admin-tokens.js.map +1 -0
- package/dist/gateway/console-api/handlers/audit.d.ts +8 -0
- package/dist/gateway/console-api/handlers/audit.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/audit.js +19 -0
- package/dist/gateway/console-api/handlers/audit.js.map +1 -0
- package/dist/gateway/console-api/handlers/audit.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/audit.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/audit.test.js +241 -0
- package/dist/gateway/console-api/handlers/audit.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/data-settings.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/data-settings.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/data-settings.test.js +264 -0
- package/dist/gateway/console-api/handlers/data-settings.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/index.d.ts +4 -0
- package/dist/gateway/console-api/handlers/index.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/index.js +24 -0
- package/dist/gateway/console-api/handlers/index.js.map +1 -0
- package/dist/gateway/console-api/handlers/keys.d.ts +13 -0
- package/dist/gateway/console-api/handlers/keys.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/keys.js +128 -0
- package/dist/gateway/console-api/handlers/keys.js.map +1 -0
- package/dist/gateway/console-api/handlers/keys.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/keys.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/keys.test.js +166 -0
- package/dist/gateway/console-api/handlers/keys.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/network-buyer.d.ts +22 -0
- package/dist/gateway/console-api/handlers/network-buyer.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/network-buyer.js +39 -0
- package/dist/gateway/console-api/handlers/network-buyer.js.map +1 -0
- package/dist/gateway/console-api/handlers/network-mapping.d.ts +33 -0
- package/dist/gateway/console-api/handlers/network-mapping.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/network-mapping.js +219 -0
- package/dist/gateway/console-api/handlers/network-mapping.js.map +1 -0
- package/dist/gateway/console-api/handlers/network-test-helpers.d.ts +35 -0
- package/dist/gateway/console-api/handlers/network-test-helpers.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/network-test-helpers.js +121 -0
- package/dist/gateway/console-api/handlers/network-test-helpers.js.map +1 -0
- package/dist/gateway/console-api/handlers/network.d.ts +15 -0
- package/dist/gateway/console-api/handlers/network.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/network.js +57 -0
- package/dist/gateway/console-api/handlers/network.js.map +1 -0
- package/dist/gateway/console-api/handlers/network.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/network.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/network.test.js +383 -0
- package/dist/gateway/console-api/handlers/network.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/org.d.ts +10 -0
- package/dist/gateway/console-api/handlers/org.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/org.js +150 -0
- package/dist/gateway/console-api/handlers/org.js.map +1 -0
- package/dist/gateway/console-api/handlers/peer-lists.d.ts +5 -0
- package/dist/gateway/console-api/handlers/peer-lists.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/peer-lists.js +43 -0
- package/dist/gateway/console-api/handlers/peer-lists.js.map +1 -0
- package/dist/gateway/console-api/handlers/presets.d.ts +9 -0
- package/dist/gateway/console-api/handlers/presets.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/presets.js +79 -0
- package/dist/gateway/console-api/handlers/presets.js.map +1 -0
- package/dist/gateway/console-api/handlers/routing.d.ts +5 -0
- package/dist/gateway/console-api/handlers/routing.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/routing.js +20 -0
- package/dist/gateway/console-api/handlers/routing.js.map +1 -0
- package/dist/gateway/console-api/handlers/settings.d.ts +10 -0
- package/dist/gateway/console-api/handlers/settings.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/settings.js +38 -0
- package/dist/gateway/console-api/handlers/settings.js.map +1 -0
- package/dist/gateway/console-api/handlers/status.d.ts +9 -0
- package/dist/gateway/console-api/handlers/status.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/status.js +47 -0
- package/dist/gateway/console-api/handlers/status.js.map +1 -0
- package/dist/gateway/console-api/handlers/status.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/status.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/status.test.js +82 -0
- package/dist/gateway/console-api/handlers/status.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/usage.d.ts +10 -0
- package/dist/gateway/console-api/handlers/usage.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/usage.js +68 -0
- package/dist/gateway/console-api/handlers/usage.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-card-link.d.ts +29 -0
- package/dist/gateway/console-api/handlers/wallet-card-link.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-card-link.js +46 -0
- package/dist/gateway/console-api/handlers/wallet-card-link.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-chain.d.ts +26 -0
- package/dist/gateway/console-api/handlers/wallet-chain.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-chain.js +80 -0
- package/dist/gateway/console-api/handlers/wallet-chain.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-mapping.d.ts +45 -0
- package/dist/gateway/console-api/handlers/wallet-mapping.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-mapping.js +202 -0
- package/dist/gateway/console-api/handlers/wallet-mapping.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-operator.d.ts +41 -0
- package/dist/gateway/console-api/handlers/wallet-operator.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-operator.js +198 -0
- package/dist/gateway/console-api/handlers/wallet-operator.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-operator.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/wallet-operator.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet-operator.test.js +195 -0
- package/dist/gateway/console-api/handlers/wallet-operator.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet.d.ts +61 -0
- package/dist/gateway/console-api/handlers/wallet.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet.js +221 -0
- package/dist/gateway/console-api/handlers/wallet.js.map +1 -0
- package/dist/gateway/console-api/handlers/wallet.test.d.ts +2 -0
- package/dist/gateway/console-api/handlers/wallet.test.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/wallet.test.js +581 -0
- package/dist/gateway/console-api/handlers/wallet.test.js.map +1 -0
- package/dist/gateway/console-api/handlers/workspaces.d.ts +12 -0
- package/dist/gateway/console-api/handlers/workspaces.d.ts.map +1 -0
- package/dist/gateway/console-api/handlers/workspaces.js +96 -0
- package/dist/gateway/console-api/handlers/workspaces.js.map +1 -0
- package/dist/gateway/console-api/operator-types.d.ts +68 -0
- package/dist/gateway/console-api/operator-types.d.ts.map +1 -0
- package/dist/gateway/console-api/operator-types.js +21 -0
- package/dist/gateway/console-api/operator-types.js.map +1 -0
- package/dist/gateway/console-api/router.d.ts +97 -0
- package/dist/gateway/console-api/router.d.ts.map +1 -0
- package/dist/gateway/console-api/router.js +69 -0
- package/dist/gateway/console-api/router.js.map +1 -0
- package/dist/gateway/console-api/routes.test.d.ts +2 -0
- package/dist/gateway/console-api/routes.test.d.ts.map +1 -0
- package/dist/gateway/console-api/routes.test.js +331 -0
- package/dist/gateway/console-api/routes.test.js.map +1 -0
- package/dist/gateway/console-api/serialize.d.ts +33 -0
- package/dist/gateway/console-api/serialize.d.ts.map +1 -0
- package/dist/gateway/console-api/serialize.js +179 -0
- package/dist/gateway/console-api/serialize.js.map +1 -0
- package/dist/gateway/console-api/server.d.ts +38 -0
- package/dist/gateway/console-api/server.d.ts.map +1 -0
- package/dist/gateway/console-api/server.js +308 -0
- package/dist/gateway/console-api/server.js.map +1 -0
- package/dist/gateway/console-api/server.test.d.ts +2 -0
- package/dist/gateway/console-api/server.test.d.ts.map +1 -0
- package/dist/gateway/console-api/server.test.js +149 -0
- package/dist/gateway/console-api/server.test.js.map +1 -0
- package/dist/gateway/console-api/test-support.d.ts +59 -0
- package/dist/gateway/console-api/test-support.d.ts.map +1 -0
- package/dist/gateway/console-api/test-support.js +120 -0
- package/dist/gateway/console-api/test-support.js.map +1 -0
- package/dist/gateway/console-api/types.d.ts +779 -0
- package/dist/gateway/console-api/types.d.ts.map +1 -0
- package/dist/gateway/console-api/types.js +6 -0
- package/dist/gateway/console-api/types.js.map +1 -0
- package/dist/gateway/console-location.d.ts +21 -0
- package/dist/gateway/console-location.d.ts.map +1 -0
- package/dist/gateway/console-location.js +41 -0
- package/dist/gateway/console-location.js.map +1 -0
- package/dist/gateway/console-recovery.d.ts +34 -0
- package/dist/gateway/console-recovery.d.ts.map +1 -0
- package/dist/gateway/console-recovery.js +94 -0
- package/dist/gateway/console-recovery.js.map +1 -0
- package/dist/gateway/console-recovery.test.d.ts +2 -0
- package/dist/gateway/console-recovery.test.d.ts.map +1 -0
- package/dist/gateway/console-recovery.test.js +106 -0
- package/dist/gateway/console-recovery.test.js.map +1 -0
- package/dist/gateway/console.d.ts +18 -0
- package/dist/gateway/console.d.ts.map +1 -0
- package/dist/gateway/console.js +101 -0
- package/dist/gateway/console.js.map +1 -0
- package/dist/gateway/console.test.d.ts +2 -0
- package/dist/gateway/console.test.d.ts.map +1 -0
- package/dist/gateway/console.test.js +165 -0
- package/dist/gateway/console.test.js.map +1 -0
- package/dist/gateway/errors.d.ts +3 -0
- package/dist/gateway/errors.d.ts.map +1 -0
- package/dist/gateway/errors.js +5 -0
- package/dist/gateway/errors.js.map +1 -0
- package/dist/gateway/exposure.d.ts +33 -0
- package/dist/gateway/exposure.d.ts.map +1 -0
- package/dist/gateway/exposure.js +146 -0
- package/dist/gateway/exposure.js.map +1 -0
- package/dist/gateway/exposure.test.d.ts +2 -0
- package/dist/gateway/exposure.test.d.ts.map +1 -0
- package/dist/gateway/exposure.test.js +93 -0
- package/dist/gateway/exposure.test.js.map +1 -0
- package/dist/gateway/gateway-policy.test.d.ts +2 -0
- package/dist/gateway/gateway-policy.test.d.ts.map +1 -0
- package/dist/gateway/gateway-policy.test.js +404 -0
- package/dist/gateway/gateway-policy.test.js.map +1 -0
- package/dist/gateway/gateway.test.js +47 -25
- package/dist/gateway/gateway.test.js.map +1 -1
- package/dist/gateway/keys.d.ts +2 -0
- package/dist/gateway/keys.d.ts.map +1 -1
- package/dist/gateway/keys.js +2 -0
- package/dist/gateway/keys.js.map +1 -1
- package/dist/gateway/limits.d.ts +32 -8
- package/dist/gateway/limits.d.ts.map +1 -1
- package/dist/gateway/limits.js +27 -11
- package/dist/gateway/limits.js.map +1 -1
- package/dist/gateway/observability.d.ts +51 -0
- package/dist/gateway/observability.d.ts.map +1 -0
- package/dist/gateway/observability.js +136 -0
- package/dist/gateway/observability.js.map +1 -0
- package/dist/gateway/policy-resolver.d.ts +73 -0
- package/dist/gateway/policy-resolver.d.ts.map +1 -0
- package/dist/gateway/policy-resolver.js +142 -0
- package/dist/gateway/policy-resolver.js.map +1 -0
- package/dist/gateway/policy-resolver.test.d.ts +2 -0
- package/dist/gateway/policy-resolver.test.d.ts.map +1 -0
- package/dist/gateway/policy-resolver.test.js +273 -0
- package/dist/gateway/policy-resolver.test.js.map +1 -0
- package/dist/gateway/request-errors.test.d.ts +2 -0
- package/dist/gateway/request-errors.test.d.ts.map +1 -0
- package/dist/gateway/request-errors.test.js +108 -0
- package/dist/gateway/request-errors.test.js.map +1 -0
- package/dist/gateway/request-shaping.d.ts +25 -0
- package/dist/gateway/request-shaping.d.ts.map +1 -0
- package/dist/gateway/request-shaping.js +66 -0
- package/dist/gateway/request-shaping.js.map +1 -0
- package/dist/gateway/response-usage.d.ts +35 -0
- package/dist/gateway/response-usage.d.ts.map +1 -0
- package/dist/gateway/response-usage.js +167 -0
- package/dist/gateway/response-usage.js.map +1 -0
- package/dist/gateway/response-usage.test.d.ts +2 -0
- package/dist/gateway/response-usage.test.d.ts.map +1 -0
- package/dist/gateway/response-usage.test.js +78 -0
- package/dist/gateway/response-usage.test.js.map +1 -0
- package/dist/gateway/runtime.d.ts +25 -0
- package/dist/gateway/runtime.d.ts.map +1 -1
- package/dist/gateway/runtime.js +39 -19
- package/dist/gateway/runtime.js.map +1 -1
- package/dist/gateway/server.d.ts +68 -2
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +532 -116
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/services/audit.d.ts +16 -0
- package/dist/gateway/services/audit.d.ts.map +1 -0
- package/dist/gateway/services/audit.js +18 -0
- package/dist/gateway/services/audit.js.map +1 -0
- package/dist/gateway/services/context.d.ts +66 -0
- package/dist/gateway/services/context.d.ts.map +1 -0
- package/dist/gateway/services/context.js +52 -0
- package/dist/gateway/services/context.js.map +1 -0
- package/dist/gateway/services/keys.d.ts +78 -0
- package/dist/gateway/services/keys.d.ts.map +1 -0
- package/dist/gateway/services/keys.js +232 -0
- package/dist/gateway/services/keys.js.map +1 -0
- package/dist/gateway/services/members.d.ts +72 -0
- package/dist/gateway/services/members.d.ts.map +1 -0
- package/dist/gateway/services/members.js +161 -0
- package/dist/gateway/services/members.js.map +1 -0
- package/dist/gateway/services/network.d.ts +36 -0
- package/dist/gateway/services/network.d.ts.map +1 -0
- package/dist/gateway/services/network.js +147 -0
- package/dist/gateway/services/network.js.map +1 -0
- package/dist/gateway/services/operator.d.ts +98 -0
- package/dist/gateway/services/operator.d.ts.map +1 -0
- package/dist/gateway/services/operator.js +170 -0
- package/dist/gateway/services/operator.js.map +1 -0
- package/dist/gateway/services/operator.test.d.ts +2 -0
- package/dist/gateway/services/operator.test.d.ts.map +1 -0
- package/dist/gateway/services/operator.test.js +184 -0
- package/dist/gateway/services/operator.test.js.map +1 -0
- package/dist/gateway/services/peer-lists.d.ts +20 -0
- package/dist/gateway/services/peer-lists.d.ts.map +1 -0
- package/dist/gateway/services/peer-lists.js +134 -0
- package/dist/gateway/services/peer-lists.js.map +1 -0
- package/dist/gateway/services/presets.d.ts +34 -0
- package/dist/gateway/services/presets.d.ts.map +1 -0
- package/dist/gateway/services/presets.js +134 -0
- package/dist/gateway/services/presets.js.map +1 -0
- package/dist/gateway/services/routing.d.ts +13 -0
- package/dist/gateway/services/routing.d.ts.map +1 -0
- package/dist/gateway/services/routing.js +18 -0
- package/dist/gateway/services/routing.js.map +1 -0
- package/dist/gateway/services/services.test.d.ts +2 -0
- package/dist/gateway/services/services.test.d.ts.map +1 -0
- package/dist/gateway/services/services.test.js +476 -0
- package/dist/gateway/services/services.test.js.map +1 -0
- package/dist/gateway/services/settings.d.ts +68 -0
- package/dist/gateway/services/settings.d.ts.map +1 -0
- package/dist/gateway/services/settings.js +580 -0
- package/dist/gateway/services/settings.js.map +1 -0
- package/dist/gateway/services/tokens.d.ts +29 -0
- package/dist/gateway/services/tokens.d.ts.map +1 -0
- package/dist/gateway/services/tokens.js +48 -0
- package/dist/gateway/services/tokens.js.map +1 -0
- package/dist/gateway/services/usage.d.ts +55 -0
- package/dist/gateway/services/usage.d.ts.map +1 -0
- package/dist/gateway/services/usage.js +225 -0
- package/dist/gateway/services/usage.js.map +1 -0
- package/dist/gateway/services/wallet-address-env.test.d.ts +2 -0
- package/dist/gateway/services/wallet-address-env.test.d.ts.map +1 -0
- package/dist/gateway/services/wallet-address-env.test.js +119 -0
- package/dist/gateway/services/wallet-address-env.test.js.map +1 -0
- package/dist/gateway/services/wallet-address.d.ts +40 -0
- package/dist/gateway/services/wallet-address.d.ts.map +1 -0
- package/dist/gateway/services/wallet-address.js +116 -0
- package/dist/gateway/services/wallet-address.js.map +1 -0
- package/dist/gateway/services/wallet-address.test.d.ts +2 -0
- package/dist/gateway/services/wallet-address.test.d.ts.map +1 -0
- package/dist/gateway/services/wallet-address.test.js +84 -0
- package/dist/gateway/services/wallet-address.test.js.map +1 -0
- package/dist/gateway/services/workspaces.d.ts +75 -0
- package/dist/gateway/services/workspaces.d.ts.map +1 -0
- package/dist/gateway/services/workspaces.js +228 -0
- package/dist/gateway/services/workspaces.js.map +1 -0
- package/dist/gateway/spend-durability.test.d.ts +2 -0
- package/dist/gateway/spend-durability.test.d.ts.map +1 -0
- package/dist/gateway/spend-durability.test.js +330 -0
- package/dist/gateway/spend-durability.test.js.map +1 -0
- package/dist/gateway/spend-feed.d.ts +11 -1
- package/dist/gateway/spend-feed.d.ts.map +1 -1
- package/dist/gateway/spend-feed.js +17 -4
- package/dist/gateway/spend-feed.js.map +1 -1
- package/dist/gateway/spend-feed.test.d.ts +2 -0
- package/dist/gateway/spend-feed.test.d.ts.map +1 -0
- package/dist/gateway/spend-feed.test.js +34 -0
- package/dist/gateway/spend-feed.test.js.map +1 -0
- package/dist/gateway/store-data.test.d.ts +2 -0
- package/dist/gateway/store-data.test.d.ts.map +1 -0
- package/dist/gateway/store-data.test.js +346 -0
- package/dist/gateway/store-data.test.js.map +1 -0
- package/dist/gateway/store-migrations.d.ts +6 -0
- package/dist/gateway/store-migrations.d.ts.map +1 -0
- package/dist/gateway/store-migrations.js +301 -0
- package/dist/gateway/store-migrations.js.map +1 -0
- package/dist/gateway/store.d.ts +595 -10
- package/dist/gateway/store.d.ts.map +1 -1
- package/dist/gateway/store.js +1242 -120
- package/dist/gateway/store.js.map +1 -1
- package/dist/gateway/store.test.d.ts +2 -0
- package/dist/gateway/store.test.d.ts.map +1 -0
- package/dist/gateway/store.test.js +185 -0
- package/dist/gateway/store.test.js.map +1 -0
- package/dist/proxy/buyer-chain-reader.d.ts +68 -0
- package/dist/proxy/buyer-chain-reader.d.ts.map +1 -0
- package/dist/proxy/buyer-chain-reader.js +152 -0
- package/dist/proxy/buyer-chain-reader.js.map +1 -0
- package/dist/proxy/buyer-chain-reader.test.d.ts +2 -0
- package/dist/proxy/buyer-chain-reader.test.d.ts.map +1 -0
- package/dist/proxy/buyer-chain-reader.test.js +102 -0
- package/dist/proxy/buyer-chain-reader.test.js.map +1 -0
- package/dist/proxy/buyer-proxy.d.ts +169 -3
- package/dist/proxy/buyer-proxy.d.ts.map +1 -1
- package/dist/proxy/buyer-proxy.js +873 -117
- package/dist/proxy/buyer-proxy.js.map +1 -1
- package/dist/proxy/buyer-proxy.test.js +31 -0
- package/dist/proxy/buyer-proxy.test.js.map +1 -1
- package/dist/proxy/chain-read-cache.d.ts +47 -0
- package/dist/proxy/chain-read-cache.d.ts.map +1 -0
- package/dist/proxy/chain-read-cache.js +110 -0
- package/dist/proxy/chain-read-cache.js.map +1 -0
- package/dist/proxy/chain-read-cache.test.d.ts +2 -0
- package/dist/proxy/chain-read-cache.test.d.ts.map +1 -0
- package/dist/proxy/chain-read-cache.test.js +75 -0
- package/dist/proxy/chain-read-cache.test.js.map +1 -0
- package/dist/proxy/chain-rpc-test-support.d.ts +31 -0
- package/dist/proxy/chain-rpc-test-support.d.ts.map +1 -0
- package/dist/proxy/chain-rpc-test-support.js +136 -0
- package/dist/proxy/chain-rpc-test-support.js.map +1 -0
- package/dist/proxy/chain-rpc.d.ts +121 -0
- package/dist/proxy/chain-rpc.d.ts.map +1 -0
- package/dist/proxy/chain-rpc.js +420 -0
- package/dist/proxy/chain-rpc.js.map +1 -0
- package/dist/proxy/chain-rpc.test.d.ts +2 -0
- package/dist/proxy/chain-rpc.test.d.ts.map +1 -0
- package/dist/proxy/chain-rpc.test.js +180 -0
- package/dist/proxy/chain-rpc.test.js.map +1 -0
- package/dist/proxy/deposit-watch-hub.d.ts +47 -0
- package/dist/proxy/deposit-watch-hub.d.ts.map +1 -0
- package/dist/proxy/deposit-watch-hub.js +111 -0
- package/dist/proxy/deposit-watch-hub.js.map +1 -0
- package/dist/proxy/deposit-watch-hub.test.d.ts +2 -0
- package/dist/proxy/deposit-watch-hub.test.d.ts.map +1 -0
- package/dist/proxy/deposit-watch-hub.test.js +133 -0
- package/dist/proxy/deposit-watch-hub.test.js.map +1 -0
- package/dist/proxy/deposit-watcher.d.ts +44 -4
- package/dist/proxy/deposit-watcher.d.ts.map +1 -1
- package/dist/proxy/deposit-watcher.js +76 -11
- package/dist/proxy/deposit-watcher.js.map +1 -1
- package/dist/proxy/deposit-watcher.test.js +54 -1
- package/dist/proxy/deposit-watcher.test.js.map +1 -1
- package/dist/proxy/gateway-policy.test.d.ts +2 -0
- package/dist/proxy/gateway-policy.test.d.ts.map +1 -0
- package/dist/proxy/gateway-policy.test.js +576 -0
- package/dist/proxy/gateway-policy.test.js.map +1 -0
- package/dist/proxy/network-models.d.ts +2 -0
- package/dist/proxy/network-models.d.ts.map +1 -1
- package/dist/proxy/network-models.js +3 -1
- package/dist/proxy/network-models.js.map +1 -1
- package/dist/proxy/route-policy.d.ts +97 -0
- package/dist/proxy/route-policy.d.ts.map +1 -0
- package/dist/proxy/route-policy.js +230 -0
- package/dist/proxy/route-policy.js.map +1 -0
- package/dist/proxy/route-policy.test.d.ts +2 -0
- package/dist/proxy/route-policy.test.d.ts.map +1 -0
- package/dist/proxy/route-policy.test.js +120 -0
- package/dist/proxy/route-policy.test.js.map +1 -0
- package/dist/proxy/spend-attribution.d.ts +41 -10
- package/dist/proxy/spend-attribution.d.ts.map +1 -1
- package/dist/proxy/spend-attribution.js +133 -37
- package/dist/proxy/spend-attribution.js.map +1 -1
- package/dist/proxy/tee-control.d.ts +3 -1
- package/dist/proxy/tee-control.d.ts.map +1 -1
- package/dist/proxy/tee-control.js +5 -3
- package/dist/proxy/tee-control.js.map +1 -1
- package/dist/proxy/telemetry.d.ts +2 -1
- package/dist/proxy/telemetry.d.ts.map +1 -1
- package/dist/proxy/telemetry.js +10 -5
- package/dist/proxy/telemetry.js.map +1 -1
- package/dist/routing-policy/policy.d.ts +149 -0
- package/dist/routing-policy/policy.d.ts.map +1 -0
- package/dist/routing-policy/policy.js +450 -0
- package/dist/routing-policy/policy.js.map +1 -0
- package/dist/routing-policy/policy.test.d.ts +2 -0
- package/dist/routing-policy/policy.test.d.ts.map +1 -0
- package/dist/routing-policy/policy.test.js +134 -0
- package/dist/routing-policy/policy.test.js.map +1 -0
- package/package.json +15 -7
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { BuyerProxy } from './buyer-proxy.js';
|
|
7
|
+
import { BUYER_IDENTITY_HEADER } from './request-utils.js';
|
|
8
|
+
import { GATEWAY_CONTROL_HEADER, GATEWAY_CONTROL_SECRET_FILE, ROUTING_POLICY_HEADER, encodePolicyHeader, } from '../routing-policy/policy.js';
|
|
9
|
+
const SECRET = 'f'.repeat(64);
|
|
10
|
+
function makePeer(seed, opts) {
|
|
11
|
+
return {
|
|
12
|
+
peerId: seed.repeat(40),
|
|
13
|
+
lastSeen: Date.now(),
|
|
14
|
+
providers: ['openai'],
|
|
15
|
+
onChainReputationScore: opts.trust,
|
|
16
|
+
displayName: `Test seller ${seed}`,
|
|
17
|
+
...(opts.capabilities ? { capabilities: opts.capabilities } : {}),
|
|
18
|
+
providerPricing: { openai: { defaults: { inputUsdPerMillion: opts.input, outputUsdPerMillion: opts.output } } },
|
|
19
|
+
providerServiceApiProtocols: { openai: { services: { 'gpt-5': ['openai-chat-completions'] } } },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function startHarness(t, peers, extra = {}, withSecret = true) {
|
|
23
|
+
const dataDir = await mkdtemp(join(tmpdir(), 'antseed-gateway-policy-'));
|
|
24
|
+
let proxy;
|
|
25
|
+
// Conversation writes land in the data dir: let them finish before removing it.
|
|
26
|
+
t.after(async () => {
|
|
27
|
+
await proxy?._conversations.flush();
|
|
28
|
+
await rm(dataDir, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
if (withSecret) {
|
|
31
|
+
await mkdir(join(dataDir, 'gateway'), { recursive: true });
|
|
32
|
+
await writeFile(join(dataDir, GATEWAY_CONTROL_SECRET_FILE), `${SECRET}\n`, { mode: 0o600 });
|
|
33
|
+
}
|
|
34
|
+
const dispatched = [];
|
|
35
|
+
const node = {
|
|
36
|
+
router: { allowsPeerForPolicy: () => true, onResult: () => { } },
|
|
37
|
+
buyerIdentities: () => [{ name: 'default', address: '0x' + '1'.repeat(40) }],
|
|
38
|
+
sendRequest: async (peer, request, options) => {
|
|
39
|
+
dispatched.push({ peerId: peer.peerId, headers: request.headers, buyerIdentity: options?.buyerIdentity });
|
|
40
|
+
return { requestId: request.requestId, statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from('{}') };
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
proxy = new BuyerProxy({ port: 0, dataDir, node: node, ...extra });
|
|
44
|
+
proxy._getPeers = async () => peers;
|
|
45
|
+
proxy._cacheLastUpdatedAtMs = Date.now();
|
|
46
|
+
proxy._mergeStateFile = async () => { };
|
|
47
|
+
const server = proxy._server;
|
|
48
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
49
|
+
t.after(() => new Promise((resolve) => server.close(() => resolve())));
|
|
50
|
+
const { port } = server.address();
|
|
51
|
+
return { proxy, url: `http://127.0.0.1:${port}`, dispatched };
|
|
52
|
+
}
|
|
53
|
+
function chat(h, headers = {}, model = 'gpt-5') {
|
|
54
|
+
return fetch(`${h.url}/v1/chat/completions`, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'content-type': 'application/json', ...headers },
|
|
57
|
+
body: JSON.stringify({ model, messages: [] }),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function withPolicy(policy) {
|
|
61
|
+
return { [GATEWAY_CONTROL_HEADER]: SECRET, [ROUTING_POLICY_HEADER]: encodePolicyHeader(policy) };
|
|
62
|
+
}
|
|
63
|
+
const cheap = makePeer('a', { input: 1, output: 1, trust: 70 });
|
|
64
|
+
const pricey = makePeer('b', { input: 9, output: 9, trust: 95 });
|
|
65
|
+
test('an authenticated policy filters automatic routing and both headers are stripped', async (t) => {
|
|
66
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
67
|
+
const res = await chat(h, withPolicy({ blockedPeerIds: [pricey.peerId] }));
|
|
68
|
+
assert.equal(res.status, 200);
|
|
69
|
+
assert.equal(h.dispatched[0]?.peerId, cheap.peerId);
|
|
70
|
+
assert.equal(h.dispatched[0]?.headers[GATEWAY_CONTROL_HEADER], undefined);
|
|
71
|
+
assert.equal(h.dispatched[0]?.headers[ROUTING_POLICY_HEADER], undefined);
|
|
72
|
+
});
|
|
73
|
+
test('/v1/models under a gateway policy lists only the models and sellers the policy allows', async (t) => {
|
|
74
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
75
|
+
const list = async (headers = {}) => {
|
|
76
|
+
const res = await fetch(`${h.url}/v1/models`, { headers });
|
|
77
|
+
assert.equal(res.status, 200);
|
|
78
|
+
const body = await res.json();
|
|
79
|
+
return body.data.map((model) => [model.id, model.peers.map((peer) => peer.peerId).sort()]);
|
|
80
|
+
};
|
|
81
|
+
assert.deepEqual(await list(), [['gpt-5', [cheap.peerId, pricey.peerId]]]);
|
|
82
|
+
assert.deepEqual(await list(withPolicy({ blockedPeerIds: [pricey.peerId] })), [['gpt-5', [cheap.peerId]]]);
|
|
83
|
+
assert.deepEqual(await list(withPolicy({ maxInputUsdPerMillion: 5 })), [['gpt-5', [cheap.peerId]]]);
|
|
84
|
+
assert.deepEqual(await list(withPolicy({ allowedModels: ['other-model'] })), []);
|
|
85
|
+
assert.deepEqual(await list(withPolicy({ modelRoutes: { 'gpt-5': { peerIds: [pricey.peerId], strict: true } } })), [['gpt-5', [pricey.peerId]]]);
|
|
86
|
+
const forged = await fetch(`${h.url}/v1/models`, { headers: { [GATEWAY_CONTROL_HEADER]: 'nope', [ROUTING_POLICY_HEADER]: encodePolicyHeader({ allowedModels: [] }) } });
|
|
87
|
+
assert.equal(forged.status, 401);
|
|
88
|
+
});
|
|
89
|
+
test('sort modes change which seller is tried first', async (t) => {
|
|
90
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
91
|
+
await chat(h, withPolicy({ sort: 'trust' }));
|
|
92
|
+
await chat(h, withPolicy({ sort: 'price' }));
|
|
93
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [pricey.peerId, cheap.peerId]);
|
|
94
|
+
});
|
|
95
|
+
test('a policy sent without any control header is stripped and ignored', async (t) => {
|
|
96
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
97
|
+
const res = await chat(h, { [ROUTING_POLICY_HEADER]: encodePolicyHeader({ allowedPeerIds: [] }) });
|
|
98
|
+
assert.equal(res.status, 200);
|
|
99
|
+
assert.equal(h.dispatched.length, 1);
|
|
100
|
+
assert.equal(h.dispatched[0]?.headers[ROUTING_POLICY_HEADER], undefined);
|
|
101
|
+
assert.equal(h.dispatched[0]?.headers[GATEWAY_CONTROL_HEADER], undefined);
|
|
102
|
+
});
|
|
103
|
+
test('a wrong control secret fails closed with 401 gateway_auth_invalid, with or without a policy', async (t) => {
|
|
104
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
105
|
+
const withBadPolicy = await chat(h, {
|
|
106
|
+
[GATEWAY_CONTROL_HEADER]: 'wrong',
|
|
107
|
+
[ROUTING_POLICY_HEADER]: encodePolicyHeader({ allowedPeerIds: [] }),
|
|
108
|
+
});
|
|
109
|
+
assert.equal(withBadPolicy.status, 401);
|
|
110
|
+
assert.equal((await withBadPolicy.json()).error.code, 'gateway_auth_invalid');
|
|
111
|
+
const authOnly = await chat(h, { [GATEWAY_CONTROL_HEADER]: 'wrong' });
|
|
112
|
+
assert.equal(authOnly.status, 401);
|
|
113
|
+
assert.equal(h.dispatched.length, 0);
|
|
114
|
+
});
|
|
115
|
+
test('a mismatch re-reads a rotated secret immediately instead of waiting out the throttle', async (t) => {
|
|
116
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
117
|
+
assert.equal((await chat(h, withPolicy({}))).status, 200);
|
|
118
|
+
const rotated = 'e'.repeat(64);
|
|
119
|
+
const dataDir = h.proxy._stateDir;
|
|
120
|
+
await writeFile(join(dataDir, GATEWAY_CONTROL_SECRET_FILE), `${rotated}\n`);
|
|
121
|
+
h.proxy._controlSecretCheckedAt = Date.now();
|
|
122
|
+
h.proxy._controlSecretForcedAt = 0;
|
|
123
|
+
const res = await chat(h, { [GATEWAY_CONTROL_HEADER]: rotated, [ROUTING_POLICY_HEADER]: encodePolicyHeader({}) });
|
|
124
|
+
assert.equal(res.status, 200);
|
|
125
|
+
// The old secret is now wrong; forced re-reads are rate limited, so this
|
|
126
|
+
// one is rejected from the cache without touching the file.
|
|
127
|
+
const stale = await chat(h, withPolicy({}));
|
|
128
|
+
assert.equal(stale.status, 401);
|
|
129
|
+
});
|
|
130
|
+
test('the secret file is picked up when the gateway creates it after the buyer starts', async (t) => {
|
|
131
|
+
const h = await startHarness(t, [cheap, pricey], {}, false);
|
|
132
|
+
const before = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
133
|
+
assert.equal(before.status, 401);
|
|
134
|
+
const dataDir = h.proxy._stateDir;
|
|
135
|
+
await mkdir(join(dataDir, 'gateway'), { recursive: true });
|
|
136
|
+
await writeFile(join(dataDir, GATEWAY_CONTROL_SECRET_FILE), SECRET);
|
|
137
|
+
h.proxy._controlSecretCheckedAt = 0;
|
|
138
|
+
const after = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
139
|
+
assert.equal(after.status, 200);
|
|
140
|
+
});
|
|
141
|
+
test('a malformed authenticated policy is rejected, never routed unrestricted', async (t) => {
|
|
142
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
143
|
+
const res = await chat(h, { [GATEWAY_CONTROL_HEADER]: SECRET, [ROUTING_POLICY_HEADER]: 'bm90IGpzb24' });
|
|
144
|
+
assert.equal(res.status, 400);
|
|
145
|
+
assert.equal((await res.json()).error.code, 'invalid_routing_policy');
|
|
146
|
+
assert.equal(h.dispatched.length, 0);
|
|
147
|
+
});
|
|
148
|
+
test('a disallowed model is refused with model_not_allowed', async (t) => {
|
|
149
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
150
|
+
const res = await chat(h, withPolicy({ allowedModels: ['other-model'] }));
|
|
151
|
+
assert.equal(res.status, 403);
|
|
152
|
+
assert.equal((await res.json()).error.code, 'model_not_allowed');
|
|
153
|
+
});
|
|
154
|
+
test('hard pins the policy excludes get 403 peer_not_allowed; soft preferences are ignored', async (t) => {
|
|
155
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
156
|
+
const policy = withPolicy({ blockedPeerIds: [pricey.peerId] });
|
|
157
|
+
const headerPin = await chat(h, { ...policy, 'x-antseed-pin-peer': pricey.peerId });
|
|
158
|
+
assert.equal(headerPin.status, 403);
|
|
159
|
+
assert.equal((await headerPin.json()).error.code, 'peer_not_allowed');
|
|
160
|
+
const modelPin = await chat(h, policy, `${pricey.peerId}@gpt-5`);
|
|
161
|
+
assert.equal(modelPin.status, 403);
|
|
162
|
+
const capped = await chat(h, { ...withPolicy({ maxInputUsdPerMillion: 2 }), 'x-antseed-pin-peer': pricey.peerId });
|
|
163
|
+
assert.equal(capped.status, 403);
|
|
164
|
+
assert.match((await capped.json()).error.message, /input price \$9 over cap \$2/);
|
|
165
|
+
const strict = await chat(h, { ...withPolicy({ modelRoutes: { 'gpt-5': { peerIds: [cheap.peerId], strict: true } } }), 'x-antseed-pin-peer': pricey.peerId });
|
|
166
|
+
assert.equal(strict.status, 403);
|
|
167
|
+
const allowedPin = await chat(h, { ...policy, 'x-antseed-pin-peer': cheap.peerId });
|
|
168
|
+
assert.equal(allowedPin.status, 200);
|
|
169
|
+
const preferred = await chat(h, { ...policy, 'x-antseed-prefer-peer': pricey.peerId });
|
|
170
|
+
assert.equal(preferred.status, 200);
|
|
171
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [cheap.peerId, cheap.peerId]);
|
|
172
|
+
});
|
|
173
|
+
test('the session pin cannot escape the policy either', async (t) => {
|
|
174
|
+
const h = await startHarness(t, [cheap, pricey], { pinnedPeerId: pricey.peerId });
|
|
175
|
+
const res = await chat(h, withPolicy({ allowedPeerIds: [cheap.peerId] }));
|
|
176
|
+
assert.equal(res.status, 403);
|
|
177
|
+
assert.equal(h.dispatched.length, 0);
|
|
178
|
+
});
|
|
179
|
+
test('strict and non-strict model routes on the automatic path', async (t) => {
|
|
180
|
+
const third = makePeer('c', { input: 0.5, output: 0.5, trust: 99 });
|
|
181
|
+
const h = await startHarness(t, [cheap, pricey, third]);
|
|
182
|
+
h.proxy._node.sendRequest = async (peer, request) => {
|
|
183
|
+
h.dispatched.push({ peerId: peer.peerId, headers: request.headers });
|
|
184
|
+
const status = peer.peerId === pricey.peerId ? 503 : 200;
|
|
185
|
+
return { requestId: request.requestId, statusCode: status, headers: { 'content-type': 'application/json' }, body: Buffer.from('{}') };
|
|
186
|
+
};
|
|
187
|
+
// Non-strict: chain first (pricey fails), then the chain's next seller.
|
|
188
|
+
await chat(h, withPolicy({ modelRoutes: { 'gpt-5': { peerIds: [pricey.peerId, cheap.peerId] } } }));
|
|
189
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [pricey.peerId, cheap.peerId]);
|
|
190
|
+
h.dispatched.length = 0;
|
|
191
|
+
// Strict: only the chain may serve; its failure is returned rather than falling through.
|
|
192
|
+
const res = await chat(h, withPolicy({ modelRoutes: { 'gpt-5': { peerIds: [pricey.peerId], strict: true } } }));
|
|
193
|
+
assert.equal(res.status, 503);
|
|
194
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [pricey.peerId]);
|
|
195
|
+
});
|
|
196
|
+
test('route-preview shares routing logic and explains ineligible sellers', async (t) => {
|
|
197
|
+
const tee = makePeer('c', { input: 0.5, output: 0.5, trust: 40 });
|
|
198
|
+
const h = await startHarness(t, [cheap, pricey, tee]);
|
|
199
|
+
h.proxy._peerHealth.set(cheap.peerId, { failureStreak: 3, cooldownUntil: Date.now() + 60_000, lastFailureAt: Date.now(), lastReason: 'seller-5xx', windowStartedAt: 0, episodeStartedAt: 0, lastSuccessAt: 0 });
|
|
200
|
+
const unauth = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`);
|
|
201
|
+
assert.equal(unauth.status, 401);
|
|
202
|
+
const res = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, {
|
|
203
|
+
headers: withPolicy({ minTrustScore: 60, maxInputUsdPerMillion: 5, requireVerified: false }),
|
|
204
|
+
});
|
|
205
|
+
assert.equal(res.status, 200);
|
|
206
|
+
const body = await res.json();
|
|
207
|
+
assert.equal(body.model, 'gpt-5');
|
|
208
|
+
const byId = new Map(body.candidates.map((candidate) => [candidate['peerId'], candidate]));
|
|
209
|
+
assert.deepEqual(Object.keys(body.candidates[0]).sort(), [
|
|
210
|
+
'displayName', 'eligible', 'inputUsdPerMillion', 'outputUsdPerMillion', 'peerId', 'rank', 'reasons', 'trustScore',
|
|
211
|
+
]);
|
|
212
|
+
assert.equal(byId.get(pricey.peerId)?.['eligible'], false);
|
|
213
|
+
assert.deepEqual(byId.get(pricey.peerId)?.['reasons'], ['input price $9 over cap $5']);
|
|
214
|
+
assert.deepEqual(byId.get(tee.peerId)?.['reasons'], ['trust 40 below 60']);
|
|
215
|
+
// The only ready seller is cooling down, so routing falls back to it.
|
|
216
|
+
assert.equal(byId.get(cheap.peerId)?.['eligible'], true);
|
|
217
|
+
assert.equal(byId.get(cheap.peerId)?.['rank'], 1);
|
|
218
|
+
const verified = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: withPolicy({ requireVerified: true }) });
|
|
219
|
+
const verifiedBody = await verified.json();
|
|
220
|
+
assert.ok(verifiedBody.candidates.every((candidate) => !candidate.eligible && candidate.reasons.some((reason) => reason.startsWith('not verified'))));
|
|
221
|
+
const bad = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: { [GATEWAY_CONTROL_HEADER]: SECRET, [ROUTING_POLICY_HEADER]: '!!' } });
|
|
222
|
+
assert.equal(bad.status, 400);
|
|
223
|
+
});
|
|
224
|
+
test('requireTee only admits sellers advertising the TEE verifier, on automatic, pinned and preview paths', async (t) => {
|
|
225
|
+
const tee = makePeer('c', { input: 5, output: 5, trust: 50, capabilities: ['verifier.antseed-verifier'] });
|
|
226
|
+
const h = await startHarness(t, [cheap, pricey, tee]);
|
|
227
|
+
const policy = withPolicy({ requireTee: true });
|
|
228
|
+
assert.equal((await chat(h, policy)).status, 200);
|
|
229
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [tee.peerId]);
|
|
230
|
+
const pinned = await chat(h, { ...policy, 'x-antseed-pin-peer': cheap.peerId });
|
|
231
|
+
assert.equal(pinned.status, 403);
|
|
232
|
+
assert.match((await pinned.json()).error.message, /no TEE/);
|
|
233
|
+
const preview = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: policy });
|
|
234
|
+
const body = await preview.json();
|
|
235
|
+
const byId = new Map(body.candidates.map((candidate) => [candidate.peerId, candidate]));
|
|
236
|
+
assert.equal(byId.get(tee.peerId)?.eligible, true);
|
|
237
|
+
assert.deepEqual(byId.get(cheap.peerId)?.reasons, ['no TEE']);
|
|
238
|
+
});
|
|
239
|
+
test('restart is refused with restart_unsupported when the buyer is not supervised', async (t) => {
|
|
240
|
+
const h = await startHarness(t, [cheap]);
|
|
241
|
+
const res = await fetch(`${h.url}/_antseed/restart`, { method: 'POST', headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
242
|
+
assert.equal(res.status, 503);
|
|
243
|
+
assert.equal((await res.json()).error, 'restart_unsupported');
|
|
244
|
+
});
|
|
245
|
+
test('a config reload keeps the startup min reputation, which the router plugin also enforces until restart', async (t) => {
|
|
246
|
+
const dir = await mkdtemp(join(tmpdir(), 'antseed-reload-'));
|
|
247
|
+
t.after(() => rm(dir, { recursive: true, force: true }));
|
|
248
|
+
const configPath = join(dir, 'config.json');
|
|
249
|
+
await writeFile(configPath, JSON.stringify({ buyer: { minPeerReputation: 10 } }));
|
|
250
|
+
const previous = process.env['ANTSEED_BUYER_MIN_REPUTATION'];
|
|
251
|
+
process.env['ANTSEED_BUYER_MIN_REPUTATION'] = '65';
|
|
252
|
+
t.after(() => {
|
|
253
|
+
if (previous === undefined)
|
|
254
|
+
delete process.env['ANTSEED_BUYER_MIN_REPUTATION'];
|
|
255
|
+
else
|
|
256
|
+
process.env['ANTSEED_BUYER_MIN_REPUTATION'] = previous;
|
|
257
|
+
});
|
|
258
|
+
const h = await startHarness(t, [cheap], { configPath, minPeerReputation: 65 });
|
|
259
|
+
await h.proxy._reloadRoutingPreferences();
|
|
260
|
+
assert.equal(h.proxy._minPeerReputation, 65);
|
|
261
|
+
delete process.env['ANTSEED_BUYER_MIN_REPUTATION'];
|
|
262
|
+
await h.proxy._reloadRoutingPreferences();
|
|
263
|
+
assert.equal(h.proxy._minPeerReputation, 65);
|
|
264
|
+
});
|
|
265
|
+
test('restart requires gateway auth, answers 202 and then runs the shutdown hook', async (t) => {
|
|
266
|
+
let restarts = 0;
|
|
267
|
+
const h = await startHarness(t, [cheap], { onRestartRequested: () => { restarts += 1; }, minRestartIntervalMs: 0 });
|
|
268
|
+
const denied = await fetch(`${h.url}/_antseed/restart`, { method: 'POST' });
|
|
269
|
+
assert.equal(denied.status, 401);
|
|
270
|
+
assert.equal(restarts, 0);
|
|
271
|
+
const accepted = await fetch(`${h.url}/_antseed/restart`, { method: 'POST', headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
272
|
+
assert.equal(accepted.status, 202);
|
|
273
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
274
|
+
assert.equal(restarts, 1);
|
|
275
|
+
});
|
|
276
|
+
test('a restart is refused with 429 until the minimum interval since the buyer started has passed', async (t) => {
|
|
277
|
+
let restarts = 0;
|
|
278
|
+
const h = await startHarness(t, [cheap], { onRestartRequested: () => { restarts += 1; } });
|
|
279
|
+
const refused = await fetch(`${h.url}/_antseed/restart`, { method: 'POST', headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
280
|
+
assert.equal(refused.status, 429);
|
|
281
|
+
assert.equal((await refused.json()).error, 'restart_too_soon');
|
|
282
|
+
assert.ok(Number(refused.headers.get('retry-after')) > 0);
|
|
283
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
284
|
+
assert.equal(restarts, 0);
|
|
285
|
+
});
|
|
286
|
+
test('balances reads chain state per identity and caches it', async (t) => {
|
|
287
|
+
let reads = 0;
|
|
288
|
+
const reader = {
|
|
289
|
+
getBuyerBalance: async () => { reads += 1; return { available: 1500000n, reserved: 250000n }; },
|
|
290
|
+
getUSDCBalance: async () => 3000000n,
|
|
291
|
+
getBuyerCreditLimit: async () => 10000000n,
|
|
292
|
+
getOperator: async () => '0x0000000000000000000000000000000000000000',
|
|
293
|
+
};
|
|
294
|
+
const h = await startHarness(t, [cheap], { balanceReader: reader });
|
|
295
|
+
const headers = { [GATEWAY_CONTROL_HEADER]: SECRET };
|
|
296
|
+
assert.equal((await fetch(`${h.url}/_antseed/balances`)).status, 401);
|
|
297
|
+
const res = await fetch(`${h.url}/_antseed/balances?identity=default`, { headers });
|
|
298
|
+
assert.deepEqual(await res.json(), {
|
|
299
|
+
address: '0x' + '1'.repeat(40),
|
|
300
|
+
available: '1.500000',
|
|
301
|
+
reserved: '0.250000',
|
|
302
|
+
walletUsdc: '3.000000',
|
|
303
|
+
creditLimit: '10.000000',
|
|
304
|
+
operator: null,
|
|
305
|
+
});
|
|
306
|
+
await fetch(`${h.url}/_antseed/balances`, { headers });
|
|
307
|
+
assert.equal(reads, 1);
|
|
308
|
+
});
|
|
309
|
+
test('peers endpoint exposes the extra picker fields', async (t) => {
|
|
310
|
+
const peer = { ...cheap, maxConcurrency: 4, currentLoad: 1, onChainChannelCount: 7, onChainTotalVolumeUsdcMicros: 99, onChainLastSettledAtSec: 123, onChainSybilRisk: 0.1 };
|
|
311
|
+
const h = await startHarness(t, [peer]);
|
|
312
|
+
const body = await (await fetch(`${h.url}/_antseed/peers`)).json();
|
|
313
|
+
assert.equal(body.peers[0]?.['maxConcurrency'], 4);
|
|
314
|
+
assert.equal(body.peers[0]?.['currentLoad'], 1);
|
|
315
|
+
assert.equal(body.peers[0]?.['onChainChannelCount'], 7);
|
|
316
|
+
assert.equal(body.peers[0]?.['onChainTotalVolumeUsdcMicros'], 99);
|
|
317
|
+
assert.equal(body.peers[0]?.['onChainLastSettledAtSec'], 123);
|
|
318
|
+
assert.equal(body.peers[0]?.['onChainSybilRisk'], 0.1);
|
|
319
|
+
});
|
|
320
|
+
test('deposit watcher status and mode are addressable per identity', async (t) => {
|
|
321
|
+
const h = await startHarness(t, [cheap]);
|
|
322
|
+
const modes = [];
|
|
323
|
+
const watcher = { status: () => ({ mode: 'idle' }), promote: () => modes.push('active'), demote: () => modes.push('background') };
|
|
324
|
+
h.proxy.setDepositWatcher(watcher);
|
|
325
|
+
h.proxy._buyerIdentities = { ensure: async (name) => name === 'team-a' };
|
|
326
|
+
h.proxy.setIdentityDepositWatcher('team-a', { ...watcher, status: () => ({ mode: 'team' }) });
|
|
327
|
+
const status = await (await fetch(`${h.url}/_antseed/deposits/status?identity=team-a`)).json();
|
|
328
|
+
assert.equal(status['watcher'], true);
|
|
329
|
+
assert.deepEqual(status['status'], { mode: 'team' });
|
|
330
|
+
const watch = await fetch(`${h.url}/_antseed/deposits/watch`, { method: 'POST', body: JSON.stringify({ mode: 'active', identity: 'team-a' }) });
|
|
331
|
+
assert.equal(watch.status, 200);
|
|
332
|
+
assert.deepEqual(modes, ['active']);
|
|
333
|
+
h.proxy.setIdentityDepositWatcher('team-a', null);
|
|
334
|
+
const missing = await (await fetch(`${h.url}/_antseed/deposits/status?identity=team-a`)).json();
|
|
335
|
+
assert.equal(missing['watcher'], false);
|
|
336
|
+
assert.equal(missing['reason'], 'identity-not-watched');
|
|
337
|
+
assert.equal((await fetch(`${h.url}/_antseed/deposits/status?identity=nobody`)).status, 404);
|
|
338
|
+
});
|
|
339
|
+
test('paying as a non-default buyer identity requires the gateway control secret once one exists', async (t) => {
|
|
340
|
+
const h = await startHarness(t, [cheap]);
|
|
341
|
+
h.proxy._buyerIdentities = { ensure: async (name) => name === 'team-a' };
|
|
342
|
+
const identity = { [BUYER_IDENTITY_HEADER]: 'Team-A' };
|
|
343
|
+
const refused = await chat(h, identity);
|
|
344
|
+
assert.equal(refused.status, 401);
|
|
345
|
+
assert.equal((await refused.json()).error.code, 'gateway_auth_required');
|
|
346
|
+
assert.equal((await chat(h, { ...identity, [GATEWAY_CONTROL_HEADER]: 'wrong' })).status, 401);
|
|
347
|
+
assert.equal(h.dispatched.length, 0);
|
|
348
|
+
assert.equal((await chat(h, { ...identity, [GATEWAY_CONTROL_HEADER]: SECRET })).status, 200);
|
|
349
|
+
assert.equal(h.dispatched[0]?.buyerIdentity, 'team-a');
|
|
350
|
+
assert.equal(h.dispatched[0]?.headers[BUYER_IDENTITY_HEADER], undefined);
|
|
351
|
+
// The default wallet needs no secret, named or not.
|
|
352
|
+
assert.equal((await chat(h, { [BUYER_IDENTITY_HEADER]: 'default' })).status, 200);
|
|
353
|
+
assert.equal((await chat(h)).status, 200);
|
|
354
|
+
assert.equal(h.dispatched[2]?.buyerIdentity, undefined);
|
|
355
|
+
const close = await fetch(`${h.url}/_antseed/channels/close`, { method: 'POST', body: JSON.stringify({ peerId: cheap.peerId, identity: 'team-a' }) });
|
|
356
|
+
assert.equal(close.status, 401);
|
|
357
|
+
});
|
|
358
|
+
test('without a control secret a loopback caller may still pay as a non-default buyer identity', async (t) => {
|
|
359
|
+
const h = await startHarness(t, [cheap], {}, false);
|
|
360
|
+
h.proxy._buyerIdentities = { ensure: async (name) => name === 'team-a' };
|
|
361
|
+
assert.equal((await chat(h, { [BUYER_IDENTITY_HEADER]: 'team-a' })).status, 200);
|
|
362
|
+
assert.equal(h.dispatched[0]?.buyerIdentity, 'team-a');
|
|
363
|
+
});
|
|
364
|
+
test('verification snapshot accepts the gateway control secret', async (t) => {
|
|
365
|
+
const h = await startHarness(t, [cheap]);
|
|
366
|
+
h.proxy._teeControl.ready = true;
|
|
367
|
+
assert.equal((await fetch(`${h.url}/_antseed/verification`)).status, 403);
|
|
368
|
+
const res = await fetch(`${h.url}/_antseed/verification`, { headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
369
|
+
assert.equal(res.status, 200);
|
|
370
|
+
});
|
|
371
|
+
// Requests without restrictions must route exactly as on a buyer without a
|
|
372
|
+
// gateway, down to the error message.
|
|
373
|
+
test('no policy, or one that changes nothing, routes like main; unknown models get the original error', async (t) => {
|
|
374
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
375
|
+
const expected = { type: 'model_not_found', code: 'model_not_found', message: 'No policy-allowed peer currently serves model "qwen3-coder".', param: 'model' };
|
|
376
|
+
for (const headers of [{}, { [GATEWAY_CONTROL_HEADER]: SECRET }, withPolicy({}), withPolicy({ sort: 'balanced', preferFreePeers: false, requireVerified: false, requireTee: false })]) {
|
|
377
|
+
const res = await chat(h, headers, 'qwen3-coder');
|
|
378
|
+
assert.equal(res.status, 502);
|
|
379
|
+
assert.deepEqual((await res.json()).error, expected);
|
|
380
|
+
}
|
|
381
|
+
for (const headers of [{}, withPolicy({ sort: 'balanced', preferFreePeers: false })]) {
|
|
382
|
+
assert.equal((await chat(h, headers)).status, 200);
|
|
383
|
+
}
|
|
384
|
+
// Both requests ranked the same way (balanced: higher trust first).
|
|
385
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [pricey.peerId, pricey.peerId]);
|
|
386
|
+
});
|
|
387
|
+
test('the buyer\'s own limits are judged once, by its router, not again by a gateway policy', async (t) => {
|
|
388
|
+
// The router plugin (fake: allows everyone) is where buyer.minPeerReputation
|
|
389
|
+
// is enforced; a gateway policy must not re-apply it with other inputs.
|
|
390
|
+
const h = await startHarness(t, [cheap, pricey], { minPeerReputation: 80 });
|
|
391
|
+
assert.equal((await chat(h, withPolicy({ sort: 'price' }))).status, 200);
|
|
392
|
+
assert.equal(h.dispatched[0]?.peerId, cheap.peerId);
|
|
393
|
+
// Explicit gateway restrictions still apply.
|
|
394
|
+
assert.equal((await chat(h, withPolicy({ sort: 'price', minReputation: 80 }))).status, 200);
|
|
395
|
+
assert.equal(h.dispatched[1]?.peerId, pricey.peerId);
|
|
396
|
+
});
|
|
397
|
+
// The buyer's routing preferences are the top level of the policy chain for
|
|
398
|
+
// automatic routing: a gateway policy narrows them and never loosens them.
|
|
399
|
+
// Pins are judged by the gateway policy and the hard limits only, as without
|
|
400
|
+
// a gateway.
|
|
401
|
+
const prefs60 = { preferFreePeers: false, maxInputUsdPerMillion: 25, minTrustScore: 60, allowedPeerIds: [], blockedPeerIds: [] };
|
|
402
|
+
const trust58 = makePeer('d', { input: 1, output: 1, trust: 58 });
|
|
403
|
+
test('a pin through a gateway default with an unrelated model route ignores the buyer trust preference', async (t) => {
|
|
404
|
+
const h = await startHarness(t, [trust58, pricey], { routingPreferences: prefs60 });
|
|
405
|
+
const policy = withPolicy({ modelRoutes: { 'other-model': { peerIds: [pricey.peerId] } } });
|
|
406
|
+
const res = await chat(h, policy, `${trust58.peerId}@gpt-5`);
|
|
407
|
+
assert.equal(res.status, 200);
|
|
408
|
+
assert.equal(h.dispatched[0]?.peerId, trust58.peerId);
|
|
409
|
+
// The same pin without a gateway behaves as before (pins never checked preferences).
|
|
410
|
+
assert.equal((await chat(h, {}, `${trust58.peerId}@gpt-5`)).status, 200);
|
|
411
|
+
});
|
|
412
|
+
test('a gateway policy cannot loosen the buyer trust minimum or its block list', async (t) => {
|
|
413
|
+
const h = await startHarness(t, [trust58, cheap, pricey], { routingPreferences: { ...prefs60, blockedPeerIds: [pricey.peerId] } });
|
|
414
|
+
// A lower gateway minimum changes nothing: the buyer's 60 still holds, and so does its block list.
|
|
415
|
+
assert.equal((await chat(h, withPolicy({ minTrustScore: 5, sort: 'price' }))).status, 200);
|
|
416
|
+
assert.equal(h.dispatched[0]?.peerId, cheap.peerId);
|
|
417
|
+
const preview = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: withPolicy({ minTrustScore: 5 }) });
|
|
418
|
+
const body = await preview.json();
|
|
419
|
+
const byId = new Map(body.candidates.map((candidate) => [candidate.peerId, candidate]));
|
|
420
|
+
assert.deepEqual(byId.get(trust58.peerId)?.reasons, ['buyer config: trust 58 below 60']);
|
|
421
|
+
assert.deepEqual(byId.get(pricey.peerId)?.reasons, ['buyer config: blocked']);
|
|
422
|
+
assert.equal(byId.get(cheap.peerId)?.eligible, true);
|
|
423
|
+
assert.deepEqual(body.buyer, { blockedPeerIds: [pricey.peerId.toLowerCase()], minTrustScore: 60 });
|
|
424
|
+
// A stricter gateway minimum narrows further, reported at the gateway level.
|
|
425
|
+
const stricter = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: withPolicy({ minTrustScore: 75 }) });
|
|
426
|
+
const stricterBody = await stricter.json();
|
|
427
|
+
const cheapVerdict = stricterBody.candidates.find((candidate) => candidate.peerId === cheap.peerId);
|
|
428
|
+
assert.deepEqual(cheapVerdict?.reasons, ['trust 70 below 75']);
|
|
429
|
+
});
|
|
430
|
+
test('hard buyer limits still apply to pins under a gateway policy and are named in the reason', async (t) => {
|
|
431
|
+
const h = await startHarness(t, [cheap, pricey], { minPeerReputation: 80, routingPreferences: prefs60 });
|
|
432
|
+
const res = await chat(h, { ...withPolicy({ minTrustScore: 5 }), 'x-antseed-pin-peer': cheap.peerId });
|
|
433
|
+
assert.equal(res.status, 403);
|
|
434
|
+
const error = (await res.json()).error;
|
|
435
|
+
assert.equal(error.code, 'peer_not_allowed');
|
|
436
|
+
assert.match(error.message, /buyer config: reputation 70 below 80/);
|
|
437
|
+
assert.equal((await chat(h, { ...withPolicy({ minTrustScore: 5 }), 'x-antseed-pin-peer': pricey.peerId })).status, 200);
|
|
438
|
+
const preview = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: withPolicy({}) });
|
|
439
|
+
assert.deepEqual((await preview.json()).buyer, { minReputation: 80, minTrustScore: 60 });
|
|
440
|
+
});
|
|
441
|
+
test('router-enforced buyer limits are labelled in the preview', async (t) => {
|
|
442
|
+
const h = await startHarness(t, [cheap, pricey]);
|
|
443
|
+
h.proxy._node.router = {
|
|
444
|
+
allowsPeerForPolicy: (_req, peer) => peer.peerId !== cheap.peerId,
|
|
445
|
+
explainPolicyRejection: () => 'reputation 30 below buyer minimum 40',
|
|
446
|
+
onResult: () => { },
|
|
447
|
+
};
|
|
448
|
+
const preview = await fetch(`${h.url}/_antseed/route-preview?model=gpt-5`, { headers: withPolicy({ sort: 'price' }) });
|
|
449
|
+
const body = await preview.json();
|
|
450
|
+
const byId = new Map(body.candidates.map((candidate) => [candidate.peerId, candidate]));
|
|
451
|
+
assert.deepEqual(byId.get(cheap.peerId)?.reasons, ['buyer config: reputation 30 below 40']);
|
|
452
|
+
});
|
|
453
|
+
test('under a gateway policy the buyer trust minimum still excludes, and its free-first still ranks', async (t) => {
|
|
454
|
+
const lowTrustFree = makePeer('e', { input: 0, output: 0, trust: 20 });
|
|
455
|
+
const free = makePeer('f', { input: 0, output: 0, trust: 65 });
|
|
456
|
+
const h = await startHarness(t, [cheap, lowTrustFree], { routingPreferences: { ...prefs60, preferFreePeers: true } });
|
|
457
|
+
await chat(h, withPolicy({ minTrustScore: 5 }));
|
|
458
|
+
assert.equal(h.dispatched[0]?.peerId, cheap.peerId);
|
|
459
|
+
const h2 = await startHarness(t, [cheap, free, lowTrustFree], { routingPreferences: { ...prefs60, preferFreePeers: true } });
|
|
460
|
+
await chat(h2, withPolicy({ sort: 'trust' }));
|
|
461
|
+
assert.equal(h2.dispatched[0]?.peerId, free.peerId);
|
|
462
|
+
// `preferFreePeers: false` means "not set" in a policy, so the buyer's
|
|
463
|
+
// free-first stays on; a gateway can turn it on, not off.
|
|
464
|
+
const h3 = await startHarness(t, [cheap, free, lowTrustFree], { routingPreferences: { ...prefs60, preferFreePeers: true } });
|
|
465
|
+
await chat(h3, withPolicy({ sort: 'trust', preferFreePeers: false }));
|
|
466
|
+
assert.equal(h3.dispatched[0]?.peerId, free.peerId);
|
|
467
|
+
});
|
|
468
|
+
test('the attributed-spend feed is readable only with the gateway control secret', async (t) => {
|
|
469
|
+
const h = await startHarness(t, [cheap]);
|
|
470
|
+
assert.equal((await fetch(`${h.url}/_antseed/attributed-spend?after=0`)).status, 401);
|
|
471
|
+
assert.equal((await fetch(`${h.url}/_antseed/attributed-spend?after=0`, { headers: { [GATEWAY_CONTROL_HEADER]: 'wrong' } })).status, 401);
|
|
472
|
+
const res = await fetch(`${h.url}/_antseed/attributed-spend?after=0`, { headers: { [GATEWAY_CONTROL_HEADER]: SECRET } });
|
|
473
|
+
assert.equal(res.status, 200);
|
|
474
|
+
assert.equal((await res.json()).ok, true);
|
|
475
|
+
});
|
|
476
|
+
test('without a control secret the attributed-spend feed stays readable and unacknowledged', async (t) => {
|
|
477
|
+
const h = await startHarness(t, [cheap], {}, false);
|
|
478
|
+
const res = await fetch(`${h.url}/_antseed/attributed-spend?after=0`, { headers: { [GATEWAY_CONTROL_HEADER]: 'from-another-data-dir' } });
|
|
479
|
+
assert.equal(res.status, 200);
|
|
480
|
+
assert.equal((await res.json()).ok, true);
|
|
481
|
+
});
|
|
482
|
+
test('latency is measured per seller and model', async (t) => {
|
|
483
|
+
const h = await startHarness(t, [cheap]);
|
|
484
|
+
h.proxy._recordPeerLatency(cheap.peerId, 'gpt-5', 100);
|
|
485
|
+
h.proxy._recordPeerLatency(cheap.peerId, 'GPT-5', 200);
|
|
486
|
+
h.proxy._recordPeerLatency(cheap.peerId, 'big-model', 5000);
|
|
487
|
+
assert.equal(h.proxy._peerLatency(cheap.peerId, 'gpt-5'), 130);
|
|
488
|
+
assert.equal(h.proxy._peerLatency(cheap.peerId, 'big-model'), 5000);
|
|
489
|
+
assert.equal(h.proxy._peerLatency(cheap.peerId, 'other'), null);
|
|
490
|
+
});
|
|
491
|
+
test('gateway-policy automatic routing falls back to a free seller when a paid one cannot be funded, and remembers only the seller that answered', async (t) => {
|
|
492
|
+
const paid = makePeer('a', { input: 1, output: 1, trust: 95 });
|
|
493
|
+
const free = makePeer('e', { input: 0, output: 0, trust: 70 });
|
|
494
|
+
const other = makePeer('b', { input: 2, output: 2, trust: 90 });
|
|
495
|
+
const h = await startHarness(t, [paid, other, free]);
|
|
496
|
+
h.proxy._node.sendRequest = async (peer, request) => {
|
|
497
|
+
h.dispatched.push({ peerId: peer.peerId, headers: request.headers });
|
|
498
|
+
if (peer.peerId === free.peerId) {
|
|
499
|
+
return { requestId: request.requestId, statusCode: 200, headers: { 'content-type': 'application/json' }, body: Buffer.from('{}') };
|
|
500
|
+
}
|
|
501
|
+
return {
|
|
502
|
+
requestId: request.requestId, statusCode: 402,
|
|
503
|
+
headers: { 'content-type': 'application/json', 'x-antseed-fault-attribution': 'buyer' },
|
|
504
|
+
body: Buffer.from('{"error":"payment_required","code":"insufficient_deposits"}'),
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
const gatewayPolicy = withPolicy({ sort: 'trust' });
|
|
508
|
+
const res = await chat(h, { ...gatewayPolicy, 'x-antseed-chat-session-id': 'thread-1' });
|
|
509
|
+
assert.equal(res.status, 200);
|
|
510
|
+
// The paid seller refused; the other paid one is skipped; the free one answered.
|
|
511
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [paid.peerId, free.peerId]);
|
|
512
|
+
const conversation = h.proxy._conversations.get('antseed-chat:thread-1');
|
|
513
|
+
assert.match(conversation?.pinnedModel ?? '', new RegExp(`^${free.peerId}@`));
|
|
514
|
+
// With no free seller left, the buyer's 402 reaches the client and no route is remembered.
|
|
515
|
+
const h2 = await startHarness(t, [paid]);
|
|
516
|
+
h2.proxy._node.sendRequest = h.proxy._node.sendRequest;
|
|
517
|
+
const refused = await chat(h2, { ...gatewayPolicy, 'x-antseed-chat-session-id': 'thread-2' });
|
|
518
|
+
assert.equal(refused.status, 402);
|
|
519
|
+
assert.equal(h2.proxy._conversations.get('antseed-chat:thread-2')?.pinnedModel ?? null, null);
|
|
520
|
+
});
|
|
521
|
+
test('without a gateway policy a 402 reaches the client from the first seller, as before', async (t) => {
|
|
522
|
+
const paid = makePeer('a', { input: 1, output: 1, trust: 95 });
|
|
523
|
+
const free = makePeer('e', { input: 0, output: 0, trust: 70 });
|
|
524
|
+
const h = await startHarness(t, [paid, free]);
|
|
525
|
+
h.proxy._node.sendRequest = async (peer, request) => {
|
|
526
|
+
h.dispatched.push({ peerId: peer.peerId, headers: request.headers });
|
|
527
|
+
return {
|
|
528
|
+
requestId: request.requestId, statusCode: 402,
|
|
529
|
+
headers: { 'content-type': 'application/json', 'x-antseed-fault-attribution': 'buyer' },
|
|
530
|
+
body: Buffer.from('{"error":"payment_required","code":"insufficient_deposits"}'),
|
|
531
|
+
};
|
|
532
|
+
};
|
|
533
|
+
const res = await chat(h);
|
|
534
|
+
assert.equal(res.status, 402);
|
|
535
|
+
assert.equal(h.dispatched.length, 1);
|
|
536
|
+
});
|
|
537
|
+
test('model_not_found moves to the next seller with or without a gateway policy', async (t) => {
|
|
538
|
+
const stale = makePeer('a', { input: 1, output: 1, trust: 95 });
|
|
539
|
+
const serving = makePeer('b', { input: 2, output: 2, trust: 90 });
|
|
540
|
+
const h = await startHarness(t, [stale, serving]);
|
|
541
|
+
h.proxy._refreshPeersNow = async () => { };
|
|
542
|
+
h.proxy._node.sendRequest = async (peer, request) => {
|
|
543
|
+
h.dispatched.push({ peerId: peer.peerId, headers: request.headers });
|
|
544
|
+
const notServed = peer.peerId === stale.peerId;
|
|
545
|
+
return {
|
|
546
|
+
requestId: request.requestId,
|
|
547
|
+
statusCode: notServed ? 400 : 200,
|
|
548
|
+
headers: { 'content-type': 'application/json' },
|
|
549
|
+
body: Buffer.from(JSON.stringify(notServed
|
|
550
|
+
? { error: { message: 'Service "gpt-5" is not served by this peer.', type: 'invalid_request_error', code: 'model_not_found' } }
|
|
551
|
+
: {})),
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
const viaGateway = await chat(h, withPolicy({ sort: 'trust' }));
|
|
555
|
+
assert.equal(viaGateway.status, 200);
|
|
556
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [stale.peerId, serving.peerId]);
|
|
557
|
+
h.dispatched.length = 0;
|
|
558
|
+
const plain = await chat(h);
|
|
559
|
+
assert.equal(plain.status, 200);
|
|
560
|
+
assert.deepEqual(h.dispatched.map((entry) => entry.peerId), [stale.peerId, serving.peerId]);
|
|
561
|
+
});
|
|
562
|
+
test('a seller that answers with an error does not become the chat\'s route', async (t) => {
|
|
563
|
+
const h = await startHarness(t, [cheap]);
|
|
564
|
+
h.proxy._node.sendRequest = async (peer, request) => {
|
|
565
|
+
h.dispatched.push({ peerId: peer.peerId, headers: request.headers });
|
|
566
|
+
return {
|
|
567
|
+
requestId: request.requestId, statusCode: 400,
|
|
568
|
+
headers: { 'content-type': 'application/json' },
|
|
569
|
+
body: Buffer.from('{"error":{"message":"bad request","type":"invalid_request_error"}}'),
|
|
570
|
+
};
|
|
571
|
+
};
|
|
572
|
+
const res = await chat(h, { 'x-antseed-chat-session-id': 'thread-err' });
|
|
573
|
+
assert.equal(res.status, 400);
|
|
574
|
+
assert.equal(h.proxy._conversations.get('antseed-chat:thread-err')?.pinnedModel ?? null, null);
|
|
575
|
+
});
|
|
576
|
+
//# sourceMappingURL=gateway-policy.test.js.map
|