deepline 0.3.460 → 0.3.462
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/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
- package/dist/bundling-sources/sdk/src/client.ts +8 -7366
- package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
- package/dist/bundling-sources/sdk/src/http.ts +6 -1231
- package/dist/bundling-sources/sdk/src/index.ts +4 -1
- package/dist/bundling-sources/sdk/src/play.ts +5 -5
- package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
- package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
- package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/server.ts +43 -0
- package/dist/bundling-sources/sdk/src/types.ts +15 -5
- package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/state.ts +28 -0
- package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
- package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +59 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +94 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +35 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
- package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
- package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
- package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
- package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
- package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
- package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
- package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
- package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
- package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +26 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +16 -2
- package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
- package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
- package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
- package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
- package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
- package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
- package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
- package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
- package/dist/cli/{auth-HKA6ZVHQ.mjs → auth-JDLEY7VU.mjs} +5 -4
- package/dist/cli/auth-UXKY6TCC.js +41 -0
- package/dist/cli/{billing-MTO2ZZ3G.js → billing-HXAXB3XZ.js} +152 -78
- package/dist/cli/{billing-26G44S5N.mjs → billing-SDHLBLMV.mjs} +84 -10
- package/dist/cli/{chunk-BHGII2D6.js → chunk-3ACMRZRV.js} +8 -6
- package/dist/cli/{chunk-S4Q2XCGM.mjs → chunk-3KZCFOZ6.mjs} +1 -1
- package/dist/cli/chunk-4KQ6SIBC.mjs +1038 -0
- package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
- package/dist/cli/{chunk-XAYO3Q2X.mjs → chunk-6NNVJDVR.mjs} +7 -5
- package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
- package/dist/cli/{chunk-OMM54B3X.mjs → chunk-6RNQGWFD.mjs} +16 -806
- package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
- package/dist/cli/{chunk-RDPTDDKX.js → chunk-7LFIMWMW.js} +2 -2
- package/dist/cli/chunk-7MJ6VI2T.mjs +19 -0
- package/dist/cli/chunk-7SWNPNML.js +1039 -0
- package/dist/cli/{chunk-CTRPCARW.mjs → chunk-7U3XNPOA.mjs} +267 -38
- package/dist/cli/{chunk-RBTTUYZZ.js → chunk-7VZHXVOQ.js} +1 -1
- package/dist/cli/{chunk-YVBWO647.mjs → chunk-AT636LLU.mjs} +2 -2
- package/dist/cli/{chunk-VTODQWQA.js → chunk-BGTPIMSM.js} +392 -261
- package/dist/cli/{chunk-KADIT5NV.mjs → chunk-CKSOY47X.mjs} +2 -2
- package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
- package/dist/cli/chunk-D6DXOUTO.mjs +827 -0
- package/dist/cli/{describe-QW54QQNB.js → chunk-EM4TXCCI.js} +27 -44
- package/dist/cli/chunk-F6QV42MC.mjs +91 -0
- package/dist/cli/chunk-FKVYR3QA.mjs +1039 -0
- package/dist/cli/{chunk-LMAULZLF.js → chunk-GEGW5HPZ.js} +29 -27
- package/dist/cli/{chunk-M52JQSLK.js → chunk-HUB3CCM2.js} +13 -4
- package/dist/cli/{chunk-YHTQM5XI.js → chunk-I6VHOU5O.js} +27 -27
- package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
- package/dist/cli/chunk-JF3TLIMQ.js +19 -0
- package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
- package/dist/cli/{chunk-LAWEURCT.mjs → chunk-LFXLQEZN.mjs} +1 -1
- package/dist/cli/{chunk-2PBN4SZE.js → chunk-LROWFPGN.js} +16 -16
- package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
- package/dist/cli/{chunk-LVJOFUU7.mjs → chunk-MUUQZIOF.mjs} +23 -49
- package/dist/cli/{chunk-2XHWOQF4.js → chunk-NBLSCHKK.js} +52 -50
- package/dist/cli/{chunk-526R2HON.mjs → chunk-NHRWZPWZ.mjs} +4 -2
- package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
- package/dist/cli/{chunk-W3BE3CHK.mjs → chunk-O2RX5A66.mjs} +14 -12
- package/dist/cli/{chunk-UKFZT7RF.js → chunk-OMQ23IXL.js} +2 -2
- package/dist/cli/{chunk-LJTFZOHU.js → chunk-OPJAJBD4.js} +28 -54
- package/dist/cli/{chunk-MLFR6DVF.mjs → chunk-PHSEINNH.mjs} +5 -5
- package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-PKHVSIJG.mjs} +19 -1
- package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
- package/dist/cli/{chunk-VJAEA4CS.js → chunk-QJZ6WNWD.js} +8 -8
- package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
- package/dist/cli/{chunk-RZSTT45F.mjs → chunk-S42YIQNE.mjs} +13 -8
- package/dist/cli/{chunk-YULBYKAK.mjs → chunk-S6UAJR6V.mjs} +3 -3
- package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
- package/dist/cli/{chunk-QWRHGGUH.js → chunk-UAJFWWZE.js} +20 -2
- package/dist/cli/{chunk-ZR2RLI4O.mjs → chunk-UDRPEZ5F.mjs} +223 -92
- package/dist/cli/{chunk-QGAWTBIR.js → chunk-ULK7JGGI.js} +511 -282
- package/dist/cli/chunk-V335HGX5.js +1038 -0
- package/dist/cli/{chunk-NH6JSJW6.mjs → chunk-V3MEA7NB.mjs} +7 -5
- package/dist/cli/{chunk-NRGGFVVB.js → chunk-VFGVXXZP.js} +37 -35
- package/dist/cli/chunk-VLEVVDWG.js +91 -0
- package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
- package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
- package/dist/cli/{describe-TOMIAT37.mjs → chunk-WIY6U6GD.mjs} +19 -36
- package/dist/cli/{chunk-YS2YBSJB.js → chunk-XANRM3QA.js} +6 -6
- package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
- package/dist/cli/{chunk-EJGBLXDZ.mjs → chunk-XZAFIOUQ.mjs} +1 -1
- package/dist/cli/chunk-Y4DPU4OM.js +827 -0
- package/dist/cli/chunk-YT5EODJO.js +920 -0
- package/dist/cli/{chunk-2WRO2UJ5.js → chunk-ZGQSFYD2.js} +56 -51
- package/dist/cli/{chunk-OJ6RUKVT.mjs → chunk-ZUK6LIJB.mjs} +10 -1
- package/dist/cli/command-docs.d.mts +5 -0
- package/dist/cli/command-docs.d.ts +5 -0
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-6FNFYJUC.js → csv-C56GSCEU.js} +13 -12
- package/dist/cli/{csv-MDHT4BKK.mjs → csv-L54JS7TF.mjs} +4 -3
- package/dist/cli/{db-D6AMVOEW.js → db-MOGRMZTA.js} +30 -27
- package/dist/cli/{db-74O3RFWY.mjs → db-YVBUW2DX.mjs} +10 -7
- package/dist/cli/describe-KYEULWPG.js +48 -0
- package/dist/cli/describe-NLZKKT7C.mjs +48 -0
- package/dist/cli/describe-core.d.mts +153 -5
- package/dist/cli/describe-core.d.ts +153 -5
- package/dist/cli/describe-core.js +9 -5
- package/dist/cli/describe-core.mjs +10 -6
- package/dist/cli/{executions-N4FMGVSC.js → executions-A7L4ULPP.js} +9 -7
- package/dist/cli/{executions-PVSF4HUF.mjs → executions-ZBGSTT37.mjs} +7 -5
- package/dist/cli/{feedback-OB7NANZW.mjs → feedback-G6GU37FD.mjs} +6 -5
- package/dist/cli/{feedback-WFSPCAI2.js → feedback-OHLY7RYD.js} +10 -9
- package/dist/cli/getting-started.d.mts +6 -6
- package/dist/cli/getting-started.d.ts +6 -6
- package/dist/cli/getting-started.js +2 -2
- package/dist/cli/getting-started.mjs +1 -1
- package/dist/cli/git-P76N4NDQ.js +25 -0
- package/dist/cli/{git-FHUSPAEU.mjs → git-PKZW3QD5.mjs} +5 -4
- package/dist/cli/index.js +152 -142
- package/dist/cli/index.mjs +56 -46
- package/dist/cli/{legacy-noops-ECHNA5HN.js → legacy-noops-5LM3D724.js} +8 -7
- package/dist/cli/{legacy-noops-HMK4BSCI.mjs → legacy-noops-LJJYG6YA.mjs} +5 -4
- package/dist/cli/{monitors-U7VQ3EZM.mjs → monitors-72QV4ALO.mjs} +19 -6
- package/dist/cli/{monitors-XLLFNENH.js → monitors-UX3H5DC2.js} +103 -90
- package/dist/cli/{org-6H3USO5M.mjs → org-6RRRKOCP.mjs} +9 -6
- package/dist/cli/{org-QX6ER2HN.js → org-IF7ISUVB.js} +70 -67
- package/dist/cli/pages-3SU3HKL7.js +252 -0
- package/dist/cli/pages-DXDYYKEK.mjs +252 -0
- package/dist/cli/{play-MOB2WYOR.mjs → play-AHASKRLA.mjs} +512 -1508
- package/dist/cli/{play-WNB7HBZK.js → play-EUIUVLUH.js} +1090 -2086
- package/dist/cli/{providers-CXEZ23E2.mjs → providers-GWGE3WY3.mjs} +7 -5
- package/dist/cli/{providers-7M3DISKX.js → providers-V5WU4VXJ.js} +10 -8
- package/dist/cli/{quickstart-ZFCHKHF6.mjs → quickstart-OXKQ5ZST.mjs} +5 -4
- package/dist/cli/{quickstart-CLJT4AZL.js → quickstart-QP65I5PF.js} +13 -12
- package/dist/cli/run-6MM72IGL.mjs +443 -0
- package/dist/cli/run-F3FTYS56.js +443 -0
- package/dist/cli/search-OYKOOI7A.js +32 -0
- package/dist/cli/{search-FVYWYIC3.mjs → search-ZMEBVJZB.mjs} +8 -6
- package/dist/cli/{secrets-YRLKZQS5.js → secrets-ACND5N6A.js} +16 -14
- package/dist/cli/{secrets-WAMPTQFC.mjs → secrets-XRCJFF3L.mjs} +7 -5
- package/dist/cli/{sessions-IQ332BJH.mjs → sessions-RTK3CEW6.mjs} +5 -4
- package/dist/cli/{sessions-44J6WIVU.js → sessions-ZGRJPCFF.js} +6 -5
- package/dist/cli/{settings-4IJR2I2T.js → settings-PD5KWQQZ.js} +80 -77
- package/dist/cli/{settings-22S6NIFQ.mjs → settings-XDRBPRDE.mjs} +14 -11
- package/dist/cli/{setup-OZUPKKPW.mjs → setup-3HPYAOCC.mjs} +12 -10
- package/dist/cli/{setup-3FWSRNOX.js → setup-E2Q6PXHC.js} +53 -51
- package/dist/cli/{skills-5CW3NFP3.mjs → skills-OOQFMPOV.mjs} +7 -6
- package/dist/cli/skills-XYWV52KB.js +31 -0
- package/dist/cli/tools-ASCDZJCK.js +55 -0
- package/dist/cli/tools-C5ZT3UIC.mjs +55 -0
- package/dist/cli/update-5RQSEIFM.js +33 -0
- package/dist/cli/{update-IBULOV7P.mjs → update-ZWJTADIW.mjs} +9 -8
- package/dist/cli/{workflow-MVZT7MWT.mjs → workflow-23NMPAJ7.mjs} +10 -8
- package/dist/cli/{workflow-Z7FW6GT2.js → workflow-TCXU5YJV.js} +20 -18
- package/dist/client-DS2IWYZF.d.ts +10 -0
- package/dist/client-DTwnz_AW.d.mts +10 -0
- package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
- package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
- package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
- package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
- package/dist/errors-d-sTrZhe.d.mts +142 -0
- package/dist/errors-yQwfgrcX.d.ts +142 -0
- package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
- package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
- package/dist/index.d.mts +11 -147
- package/dist/index.d.ts +11 -147
- package/dist/index.js +15 -11
- package/dist/index.mjs +14 -10
- package/dist/install-integrity.json +141 -104
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +2 -1
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/play-description.js +2 -2
- package/dist/plays/play-description.mjs +1 -1
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/dist/server.d.mts +17 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +76 -0
- package/dist/server.mjs +76 -0
- package/package.json +6 -1
- package/dist/cli/auth-VDOCNR7H.js +0 -40
- package/dist/cli/chunk-PQUUWFXY.js +0 -95
- package/dist/cli/chunk-QJLKYYPX.js +0 -1710
- package/dist/cli/chunk-YBWAG72P.mjs +0 -95
- package/dist/cli/git-4PMBJSH5.js +0 -24
- package/dist/cli/search-4CCQCTVD.js +0 -30
- package/dist/cli/skills-LMNM6B5F.js +0 -30
- package/dist/cli/tools-AGBBDJ7P.js +0 -45
- package/dist/cli/tools-NOPBDRGW.mjs +0 -45
- package/dist/cli/update-U3W6USVD.js +0 -32
|
@@ -1,40 +1,3 @@
|
|
|
1
|
-
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
const PARALLEL_WEBHOOK_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
4
|
-
const STANDARD_WEBHOOK_SECRET_PREFIX = 'whsec_';
|
|
5
|
-
|
|
6
|
-
type WebhookVerificationOk = {
|
|
7
|
-
ok: true;
|
|
8
|
-
mode: 'verified' | 'unsigned_non_prod';
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type WebhookVerificationFailure = {
|
|
12
|
-
ok: false;
|
|
13
|
-
status: 401 | 500;
|
|
14
|
-
code: string;
|
|
15
|
-
message: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type WebhookVerificationResult =
|
|
19
|
-
| WebhookVerificationOk
|
|
20
|
-
| WebhookVerificationFailure;
|
|
21
|
-
|
|
22
|
-
export type ProviderCallbackBindingValidationFailure = {
|
|
23
|
-
ok: false;
|
|
24
|
-
status: 409;
|
|
25
|
-
code: 'provider_callback_binding_mismatch';
|
|
26
|
-
message: string;
|
|
27
|
-
fields: string[];
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type ProviderCallbackBindingValidationResult =
|
|
31
|
-
| { ok: true }
|
|
32
|
-
| ProviderCallbackBindingValidationFailure;
|
|
33
|
-
|
|
34
|
-
function normalizedEnvFlag(value: string | undefined) {
|
|
35
|
-
return value?.trim().toLowerCase();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
1
|
function readRecord(value: unknown): Record<string, unknown> {
|
|
39
2
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
40
3
|
? (value as Record<string, unknown>)
|
|
@@ -48,94 +11,6 @@ function readString(value: unknown) {
|
|
|
48
11
|
return trimmed || null;
|
|
49
12
|
}
|
|
50
13
|
|
|
51
|
-
function readStringAtPath(record: Record<string, unknown>, path: string) {
|
|
52
|
-
const value = path.split('.').reduce<unknown>((current, part) => {
|
|
53
|
-
if (!current || typeof current !== 'object' || Array.isArray(current)) {
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
return (current as Record<string, unknown>)[part];
|
|
57
|
-
}, record);
|
|
58
|
-
return readString(value);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function addString(
|
|
62
|
-
values: Set<string>,
|
|
63
|
-
value: string | number | null | undefined,
|
|
64
|
-
) {
|
|
65
|
-
const string = readString(value);
|
|
66
|
-
if (string) values.add(string);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function genericWebhookIdsFromPayload(payload: Record<string, unknown>) {
|
|
70
|
-
const values = new Set<string>();
|
|
71
|
-
for (const path of [
|
|
72
|
-
'webhook_id',
|
|
73
|
-
'webhookId',
|
|
74
|
-
'hook_id',
|
|
75
|
-
'hookId',
|
|
76
|
-
'webhook.id',
|
|
77
|
-
'data.webhook_id',
|
|
78
|
-
'data.webhookId',
|
|
79
|
-
'data.hook_id',
|
|
80
|
-
'data.hookId',
|
|
81
|
-
'result.webhook_id',
|
|
82
|
-
'result.webhookId',
|
|
83
|
-
'result.data.webhook_id',
|
|
84
|
-
'result.data.webhookId',
|
|
85
|
-
]) {
|
|
86
|
-
addString(values, readStringAtPath(payload, path));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const events = Array.isArray(payload.events) ? payload.events : [];
|
|
90
|
-
for (const item of events) {
|
|
91
|
-
const event = readRecord(item);
|
|
92
|
-
addString(values, readStringAtPath(event, 'webhook_id'));
|
|
93
|
-
addString(values, readStringAtPath(event, 'webhookId'));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return values;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function isTheirstackWebhookBindingPayload(payload: Record<string, unknown>) {
|
|
100
|
-
return Boolean(
|
|
101
|
-
readString(payload.id) &&
|
|
102
|
-
readString(payload.search_id) &&
|
|
103
|
-
readString(payload.event_type) &&
|
|
104
|
-
readString(payload.url),
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function theirstackWebhookIdsFromPayload(payload: Record<string, unknown>) {
|
|
109
|
-
const values = new Set<string>();
|
|
110
|
-
addString(values, payload.webhook_id as string | number | null | undefined);
|
|
111
|
-
addString(values, payload.webhookId as string | number | null | undefined);
|
|
112
|
-
if (isTheirstackWebhookBindingPayload(payload)) {
|
|
113
|
-
addString(values, payload.id as string | number | null | undefined);
|
|
114
|
-
}
|
|
115
|
-
return values;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function theirstackSavedSearchIdsFromPayload(payload: Record<string, unknown>) {
|
|
119
|
-
const values = new Set<string>();
|
|
120
|
-
addString(values, payload.search_id as string | number | null | undefined);
|
|
121
|
-
addString(
|
|
122
|
-
values,
|
|
123
|
-
payload.saved_search_id as string | number | null | undefined,
|
|
124
|
-
);
|
|
125
|
-
return values;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function mismatchedFields(input: {
|
|
129
|
-
expected: string | null;
|
|
130
|
-
actual: Set<string>;
|
|
131
|
-
field: string;
|
|
132
|
-
}) {
|
|
133
|
-
if (!input.expected || input.actual.size === 0) return [];
|
|
134
|
-
return [...input.actual].some((value) => value !== input.expected)
|
|
135
|
-
? [input.field]
|
|
136
|
-
: [];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
14
|
export function theirstackSavedSearchIdFromProviderBinding(
|
|
140
15
|
providerBinding: Record<string, unknown>,
|
|
141
16
|
) {
|
|
@@ -149,185 +24,3 @@ export function theirstackSavedSearchIdFromProviderBinding(
|
|
|
149
24
|
readString(readRecord(webhook.data).search_id)
|
|
150
25
|
);
|
|
151
26
|
}
|
|
152
|
-
|
|
153
|
-
export function validateProviderCallbackBinding(input: {
|
|
154
|
-
provider: string;
|
|
155
|
-
payload: Record<string, unknown>;
|
|
156
|
-
providerBinding: Record<string, unknown>;
|
|
157
|
-
upstreamWebhookId?: string | null;
|
|
158
|
-
}): ProviderCallbackBindingValidationResult {
|
|
159
|
-
const fields =
|
|
160
|
-
input.provider === 'theirstack'
|
|
161
|
-
? [
|
|
162
|
-
...mismatchedFields({
|
|
163
|
-
expected: input.upstreamWebhookId ?? null,
|
|
164
|
-
actual: theirstackWebhookIdsFromPayload(input.payload),
|
|
165
|
-
field: 'webhook_id',
|
|
166
|
-
}),
|
|
167
|
-
...mismatchedFields({
|
|
168
|
-
expected: theirstackSavedSearchIdFromProviderBinding(
|
|
169
|
-
input.providerBinding,
|
|
170
|
-
),
|
|
171
|
-
actual: theirstackSavedSearchIdsFromPayload(input.payload),
|
|
172
|
-
field: 'search_id',
|
|
173
|
-
}),
|
|
174
|
-
]
|
|
175
|
-
: mismatchedFields({
|
|
176
|
-
expected: input.upstreamWebhookId ?? null,
|
|
177
|
-
actual: genericWebhookIdsFromPayload(input.payload),
|
|
178
|
-
field: 'webhook_id',
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
if (fields.length === 0) {
|
|
182
|
-
return { ok: true };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
ok: false,
|
|
187
|
-
status: 409,
|
|
188
|
-
code: 'provider_callback_binding_mismatch',
|
|
189
|
-
message:
|
|
190
|
-
'Callback payload provider identifiers do not match the authenticated Deepline monitor binding.',
|
|
191
|
-
fields: Array.from(new Set(fields)),
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function shouldRequireParallelWebhookSignature() {
|
|
196
|
-
const explicit = normalizedEnvFlag(
|
|
197
|
-
process.env.DEEPLINE_REQUIRE_PARALLEL_WEBHOOK_SIGNATURE,
|
|
198
|
-
);
|
|
199
|
-
if (explicit === 'true' || explicit === '1' || explicit === 'yes') {
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
if (explicit === 'false' || explicit === '0' || explicit === 'no') {
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
return process.env.NODE_ENV === 'production';
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function parallelWebhookSigningSecret() {
|
|
209
|
-
return (
|
|
210
|
-
process.env.DEEPLINE_PARALLEL_WEBHOOK_SECRET?.trim() ||
|
|
211
|
-
process.env.PARALLEL_WEBHOOK_SECRET?.trim() ||
|
|
212
|
-
null
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function signingKey(secret: string) {
|
|
217
|
-
if (secret.startsWith(STANDARD_WEBHOOK_SECRET_PREFIX)) {
|
|
218
|
-
return Buffer.from(
|
|
219
|
-
secret.slice(STANDARD_WEBHOOK_SECRET_PREFIX.length),
|
|
220
|
-
'base64',
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
return secret;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function readStandardWebhookHeader(headers: Headers, name: string) {
|
|
227
|
-
return (
|
|
228
|
-
headers.get(name) ?? headers.get(`svix-${name.replace('webhook-', '')}`)
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function parseTimestampMs(value: string) {
|
|
233
|
-
const trimmed = value.trim();
|
|
234
|
-
if (/^\d+$/.test(trimmed)) {
|
|
235
|
-
const numeric = Number(trimmed);
|
|
236
|
-
if (!Number.isFinite(numeric)) return null;
|
|
237
|
-
return numeric > 10_000_000_000 ? numeric : numeric * 1000;
|
|
238
|
-
}
|
|
239
|
-
const parsed = Date.parse(trimmed);
|
|
240
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function readSignatures(header: string) {
|
|
244
|
-
return header
|
|
245
|
-
.split(/\s+/)
|
|
246
|
-
.map((part) => part.trim())
|
|
247
|
-
.filter(Boolean)
|
|
248
|
-
.flatMap((part) => {
|
|
249
|
-
const [version, signature] = part.split(',', 2);
|
|
250
|
-
return version === 'v1' && signature ? [signature] : [];
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function signaturesEqual(expectedBase64: string, actualBase64: string) {
|
|
255
|
-
const expected = Buffer.from(expectedBase64, 'base64');
|
|
256
|
-
const actual = Buffer.from(actualBase64, 'base64');
|
|
257
|
-
if (expected.length === 0 || actual.length === 0) return false;
|
|
258
|
-
if (expected.length !== actual.length) return false;
|
|
259
|
-
return timingSafeEqual(expected, actual);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export function verifyParallelWebhookRequest(input: {
|
|
263
|
-
headers: Headers;
|
|
264
|
-
rawBody: string;
|
|
265
|
-
nowMs?: number;
|
|
266
|
-
}): WebhookVerificationResult {
|
|
267
|
-
const secret = parallelWebhookSigningSecret();
|
|
268
|
-
if (!secret) {
|
|
269
|
-
if (shouldRequireParallelWebhookSignature()) {
|
|
270
|
-
return {
|
|
271
|
-
ok: false,
|
|
272
|
-
status: 500,
|
|
273
|
-
code: 'parallel_webhook_secret_missing',
|
|
274
|
-
message: 'Parallel webhook signing secret is not configured.',
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
return { ok: true, mode: 'unsigned_non_prod' };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const webhookId = readStandardWebhookHeader(input.headers, 'webhook-id');
|
|
281
|
-
const webhookTimestamp = readStandardWebhookHeader(
|
|
282
|
-
input.headers,
|
|
283
|
-
'webhook-timestamp',
|
|
284
|
-
);
|
|
285
|
-
const webhookSignature = readStandardWebhookHeader(
|
|
286
|
-
input.headers,
|
|
287
|
-
'webhook-signature',
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
if (!webhookId || !webhookTimestamp || !webhookSignature) {
|
|
291
|
-
return {
|
|
292
|
-
ok: false,
|
|
293
|
-
status: 401,
|
|
294
|
-
code: 'parallel_webhook_signature_missing',
|
|
295
|
-
message: 'Parallel webhook signature headers are missing.',
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const timestampMs = parseTimestampMs(webhookTimestamp);
|
|
300
|
-
const nowMs = input.nowMs ?? Date.now();
|
|
301
|
-
if (
|
|
302
|
-
timestampMs === null ||
|
|
303
|
-
Math.abs(nowMs - timestampMs) > PARALLEL_WEBHOOK_SIGNATURE_TOLERANCE_MS
|
|
304
|
-
) {
|
|
305
|
-
return {
|
|
306
|
-
ok: false,
|
|
307
|
-
status: 401,
|
|
308
|
-
code: 'parallel_webhook_timestamp_invalid',
|
|
309
|
-
message: 'Parallel webhook timestamp is outside the accepted window.',
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const signedPayload = `${webhookId}.${webhookTimestamp}.${input.rawBody}`;
|
|
314
|
-
const expectedSignature = createHmac('sha256', signingKey(secret))
|
|
315
|
-
.update(signedPayload)
|
|
316
|
-
.digest('base64');
|
|
317
|
-
const signatures = readSignatures(webhookSignature);
|
|
318
|
-
if (
|
|
319
|
-
signatures.length === 0 ||
|
|
320
|
-
!signatures.some((signature) =>
|
|
321
|
-
signaturesEqual(expectedSignature, signature),
|
|
322
|
-
)
|
|
323
|
-
) {
|
|
324
|
-
return {
|
|
325
|
-
ok: false,
|
|
326
|
-
status: 401,
|
|
327
|
-
code: 'parallel_webhook_signature_invalid',
|
|
328
|
-
message: 'Parallel webhook signature is invalid.',
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return { ok: true, mode: 'verified' };
|
|
333
|
-
}
|
|
@@ -143,6 +143,9 @@ export function monitorErrorNextAction(payload: MonitorErrorPayload): string {
|
|
|
143
143
|
if (code === 'monitor_control_plane_unavailable') {
|
|
144
144
|
return 'Wait briefly, then rerun the same monitor read. No monitor state was changed.';
|
|
145
145
|
}
|
|
146
|
+
if (code === 'monitor_job_control_plane_unavailable') {
|
|
147
|
+
return 'Wait briefly, then retry the same request once, reusing its Idempotency-Key if it sent one. Deepline could not confirm whether it was applied.';
|
|
148
|
+
}
|
|
146
149
|
if (code === 'provider_monitor_identity_backfill_in_progress') {
|
|
147
150
|
return typeof retryAfterSeconds === 'number'
|
|
148
151
|
? `Wait ${retryAfterSeconds} seconds, then retry the same monitor lifecycle request once. No upstream monitor was created.`
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
// dev-bootstrap test orgs are always suppressed (see
|
|
19
19
|
// `shouldSuppressMonitorActor` + the transport-level guard in
|
|
20
20
|
// the shared Slack delivery contract).
|
|
21
|
-
// - Environments:
|
|
22
|
-
//
|
|
21
|
+
// - Environments: Production only (KAR-77). Gauntlet and local tests trigger
|
|
22
|
+
// monitor errors on purpose, and these channels resolve to the production
|
|
23
|
+
// channel IDs wherever the reporting bot token is set.
|
|
23
24
|
// - Spend: NEVER include provider spend. These payloads carry only keys,
|
|
24
25
|
// counts, and trigger metadata — no provider-cost fields.
|
|
25
26
|
|
|
@@ -95,6 +95,8 @@
|
|
|
95
95
|
"./quickstart-prompts.js": "./quickstart-prompts.ts",
|
|
96
96
|
"./signal-radars/inbound-dead-letter": "./signal-radars/inbound-dead-letter.ts",
|
|
97
97
|
"./signal-radars/inbound-dead-letter.js": "./signal-radars/inbound-dead-letter.ts",
|
|
98
|
+
"./signal-radars/inbound-failure-codes": "./signal-radars/inbound-failure-codes.ts",
|
|
99
|
+
"./signal-radars/inbound-failure-codes.js": "./signal-radars/inbound-failure-codes.ts",
|
|
98
100
|
"./signal-radars/inbound-message": "./signal-radars/inbound-message.ts",
|
|
99
101
|
"./signal-radars/inbound-message.js": "./signal-radars/inbound-message.ts",
|
|
100
102
|
"./signal-radars/inbound-queue": "./signal-radars/inbound-queue.ts",
|
|
@@ -519,6 +519,40 @@ export function tamradarCallbackRadarId(payload: Record<string, unknown>) {
|
|
|
519
519
|
);
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
export type TamradarBatchNotice = {
|
|
523
|
+
updateType: 'bulk_completed' | 'radar_failure';
|
|
524
|
+
bulkId: string;
|
|
525
|
+
itemIndex: number | null;
|
|
526
|
+
code: number | null;
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* A shared bulk callback also carries messages about the batch itself: the
|
|
531
|
+
* final `bulk_completed` summary, and a `radar_failure` for an item TamRadar
|
|
532
|
+
* refused, which never became a radar. Neither has a radar ID to route by, and
|
|
533
|
+
* neither is a finding. A message with no `bulk_id` is not one of these.
|
|
534
|
+
*/
|
|
535
|
+
export function tamradarBatchNotice(
|
|
536
|
+
payload: Record<string, unknown>,
|
|
537
|
+
): TamradarBatchNotice | null {
|
|
538
|
+
const unwrapped = unwrapTamradarPayload(payload);
|
|
539
|
+
const bulkId = readString(unwrapped.bulk_id);
|
|
540
|
+
const updateType = readString(unwrapped.update_type);
|
|
541
|
+
if (
|
|
542
|
+
!bulkId ||
|
|
543
|
+
(updateType !== 'bulk_completed' && updateType !== 'radar_failure')
|
|
544
|
+
) {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
updateType,
|
|
549
|
+
bulkId,
|
|
550
|
+
itemIndex:
|
|
551
|
+
typeof unwrapped.item_index === 'number' ? unwrapped.item_index : null,
|
|
552
|
+
code: typeof unwrapped.code === 'number' ? unwrapped.code : null,
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
522
556
|
function genericWebhookIds(payload: Record<string, unknown>) {
|
|
523
557
|
return [
|
|
524
558
|
'webhook_id',
|
|
@@ -499,3 +499,62 @@ export function providerMonitorBatchOperationRequestFingerprint(
|
|
|
499
499
|
}
|
|
500
500
|
return canonicalJson(normalized);
|
|
501
501
|
}
|
|
502
|
+
|
|
503
|
+
export type ProviderMonitorBatchChangeBucket =
|
|
504
|
+
| 'created'
|
|
505
|
+
| 'updated'
|
|
506
|
+
| 'removed';
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* What a changed result did to the provider resource, by its code. Every
|
|
510
|
+
* code a runner records with `changed: true` belongs here; the
|
|
511
|
+
* provider-monitor-batch-change-buckets test reads the runner sources and
|
|
512
|
+
* fails on one that is missing. A missing code would otherwise count as
|
|
513
|
+
* changed with no bucket, so `created + updated + removed` falls short of
|
|
514
|
+
* `changed` rather than reporting a close as a create (KAR-115).
|
|
515
|
+
*/
|
|
516
|
+
export const PROVIDER_MONITOR_BATCH_CHANGE_BUCKETS: Readonly<
|
|
517
|
+
Record<string, ProviderMonitorBatchChangeBucket>
|
|
518
|
+
> = {
|
|
519
|
+
// A new provider resource.
|
|
520
|
+
provider_batch_created: 'created',
|
|
521
|
+
provider_create_adjudicated: 'created',
|
|
522
|
+
provider_create_adopted_by_operator: 'created',
|
|
523
|
+
named_batch_create: 'created',
|
|
524
|
+
named_batch_start: 'created',
|
|
525
|
+
provider_repaired: 'created',
|
|
526
|
+
fleet_converged: 'created',
|
|
527
|
+
// An existing provider resource replaced or reconciled.
|
|
528
|
+
existing_monitor_replaced: 'updated',
|
|
529
|
+
existing_monitor_reconciled_by_identity: 'updated',
|
|
530
|
+
named_batch_update: 'updated',
|
|
531
|
+
provider_configuration_repaired: 'updated',
|
|
532
|
+
// A provider resource closed, or proven absent. A create stopped or deleted
|
|
533
|
+
// by the customer's intent before it settled ends removed.
|
|
534
|
+
upstream_deactivated: 'removed',
|
|
535
|
+
upstream_inactive_verified: 'removed',
|
|
536
|
+
already_absent_upstream: 'removed',
|
|
537
|
+
deleted_monitor_resource_closed: 'removed',
|
|
538
|
+
deleted_monitor_intent_closed: 'removed',
|
|
539
|
+
fleet_member_removed: 'removed',
|
|
540
|
+
fleet_converged_inactive: 'removed',
|
|
541
|
+
provider_batch_created_then_stopped: 'removed',
|
|
542
|
+
provider_batch_created_then_deleted: 'removed',
|
|
543
|
+
pending_create_intent_satisfied: 'removed',
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
export function providerMonitorBatchChangeBucket(input: {
|
|
547
|
+
operationKind: ProviderMonitorBatchOperationKind | undefined;
|
|
548
|
+
state: ProviderMonitorBatchResultState | undefined;
|
|
549
|
+
changed: boolean;
|
|
550
|
+
code?: string;
|
|
551
|
+
}): ProviderMonitorBatchChangeBucket | null {
|
|
552
|
+
if (input.state !== 'done' || !input.changed) return null;
|
|
553
|
+
// A runner that predates a code split still records the old code, so a
|
|
554
|
+
// deactivation stays removed whatever it reports.
|
|
555
|
+
if (input.operationKind === 'deactivate') return 'removed';
|
|
556
|
+
if (input.code === undefined) return null;
|
|
557
|
+
return Object.hasOwn(PROVIDER_MONITOR_BATCH_CHANGE_BUCKETS, input.code)
|
|
558
|
+
? PROVIDER_MONITOR_BATCH_CHANGE_BUCKETS[input.code]!
|
|
559
|
+
: null;
|
|
560
|
+
}
|
|
@@ -31,16 +31,26 @@ type ProviderMonitorUpstreamIdentityDefinition = {
|
|
|
31
31
|
* treating different authored filters as an exact duplicate.
|
|
32
32
|
*/
|
|
33
33
|
allowDistinctConfigurations?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Payload fields that never change which findings the provider resource
|
|
36
|
+
* delivers. `updates_since` only sets how far back the first delivery
|
|
37
|
+
* replays, so two monitors that differ only there watch the same feed.
|
|
38
|
+
* Claim keys written before this list existed still carry these fields;
|
|
39
|
+
* readers resolve them through `canonicalProviderMonitorIdentityClaimKey`.
|
|
40
|
+
*/
|
|
41
|
+
nonConfigurationFields?: readonly string[];
|
|
34
42
|
};
|
|
35
43
|
|
|
36
44
|
const PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS = {
|
|
37
45
|
'deepline_native.company_radar': {
|
|
38
46
|
fields: [{ name: 'radar_type' }, { name: 'domain' }],
|
|
39
47
|
allowDistinctConfigurations: true,
|
|
48
|
+
nonConfigurationFields: ['updates_since'],
|
|
40
49
|
},
|
|
41
50
|
'deepline_native.contact_radar': {
|
|
42
51
|
fields: [{ name: 'radar_type' }, { name: 'profile_url' }],
|
|
43
52
|
allowDistinctConfigurations: true,
|
|
53
|
+
nonConfigurationFields: ['updates_since'],
|
|
44
54
|
},
|
|
45
55
|
'deepline_native.industry_radar': {
|
|
46
56
|
fields: [
|
|
@@ -48,6 +58,7 @@ const PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS = {
|
|
|
48
58
|
{ name: 'industry', runtimePayloadAliases: ['keyword'] },
|
|
49
59
|
],
|
|
50
60
|
allowDistinctConfigurations: true,
|
|
61
|
+
nonConfigurationFields: ['updates_since'],
|
|
51
62
|
},
|
|
52
63
|
} as const satisfies Record<string, ProviderMonitorUpstreamIdentityDefinition>;
|
|
53
64
|
|
|
@@ -59,6 +70,8 @@ function canonicalMonitorTool(tool: string) {
|
|
|
59
70
|
: tool;
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
const CONFIGURATION_SEPARATOR = '#configuration=';
|
|
74
|
+
|
|
62
75
|
function stableJson(value: unknown): string {
|
|
63
76
|
if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;
|
|
64
77
|
if (value && typeof value === 'object') {
|
|
@@ -172,5 +185,85 @@ export function providerMonitorUpstreamIdentityClaimKey(
|
|
|
172
185
|
),
|
|
173
186
|
);
|
|
174
187
|
if (Object.keys(configuration).length === 0) return scopeKey;
|
|
175
|
-
return `${scopeKey}
|
|
188
|
+
return `${scopeKey}${CONFIGURATION_SEPARATOR}${stableJson(configuration)}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function parseJsonObject(text: string): Record<string, unknown> | null {
|
|
192
|
+
try {
|
|
193
|
+
const parsed: unknown = JSON.parse(text);
|
|
194
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
195
|
+
? (parsed as Record<string, unknown>)
|
|
196
|
+
: null;
|
|
197
|
+
} catch {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Splits a stored claim key into its scope JSON and configuration JSON. A
|
|
204
|
+
* scope value may itself contain the separator text, so the split is the one
|
|
205
|
+
* where both halves parse as JSON objects. Scope-only keys return null.
|
|
206
|
+
*/
|
|
207
|
+
function splitClaimKey(identityKey: string) {
|
|
208
|
+
let separator = identityKey.indexOf(CONFIGURATION_SEPARATOR);
|
|
209
|
+
while (separator !== -1) {
|
|
210
|
+
const scopeKey = identityKey.slice(0, separator);
|
|
211
|
+
const configuration = parseJsonObject(
|
|
212
|
+
identityKey.slice(separator + CONFIGURATION_SEPARATOR.length),
|
|
213
|
+
);
|
|
214
|
+
if (configuration && parseJsonObject(scopeKey)) {
|
|
215
|
+
return { scopeKey, configuration };
|
|
216
|
+
}
|
|
217
|
+
separator = identityKey.indexOf(CONFIGURATION_SEPARATOR, separator + 1);
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The claim key with every `nonConfigurationFields` entry removed. Two claim
|
|
224
|
+
* keys with the same canonical form occupy the same provider feed. A key that
|
|
225
|
+
* is already canonical, scope-only, or for a tool without such fields is
|
|
226
|
+
* returned unchanged, so this is idempotent and safe on any stored key.
|
|
227
|
+
*/
|
|
228
|
+
export function canonicalProviderMonitorIdentityClaimKey(
|
|
229
|
+
tool: string,
|
|
230
|
+
identityKey: string,
|
|
231
|
+
) {
|
|
232
|
+
const definition: ProviderMonitorUpstreamIdentityDefinition | undefined =
|
|
233
|
+
PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS[
|
|
234
|
+
canonicalMonitorTool(
|
|
235
|
+
tool,
|
|
236
|
+
) as keyof typeof PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS
|
|
237
|
+
];
|
|
238
|
+
const ignored = definition?.nonConfigurationFields;
|
|
239
|
+
if (!ignored?.length) return identityKey;
|
|
240
|
+
const parts = splitClaimKey(identityKey);
|
|
241
|
+
if (!parts) return identityKey;
|
|
242
|
+
const configuration = Object.fromEntries(
|
|
243
|
+
Object.entries(parts.configuration).filter(
|
|
244
|
+
([field]) => !ignored.includes(field),
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
if (Object.keys(configuration).length === 0) return parts.scopeKey;
|
|
248
|
+
return `${parts.scopeKey}${CONFIGURATION_SEPARATOR}${stableJson(configuration)}`;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Whether a claim key carries configuration beyond its scope. */
|
|
252
|
+
export function providerMonitorIdentityClaimKeyHasConfiguration(
|
|
253
|
+
identityKey: string,
|
|
254
|
+
) {
|
|
255
|
+
return splitClaimKey(identityKey) !== null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** True when the stored claim key and the identity key name the same feed. */
|
|
259
|
+
export function providerMonitorIdentityClaimKeysMatch(
|
|
260
|
+
tool: string,
|
|
261
|
+
left: string,
|
|
262
|
+
right: string,
|
|
263
|
+
) {
|
|
264
|
+
return (
|
|
265
|
+
left === right ||
|
|
266
|
+
canonicalProviderMonitorIdentityClaimKey(tool, left) ===
|
|
267
|
+
canonicalProviderMonitorIdentityClaimKey(tool, right)
|
|
268
|
+
);
|
|
176
269
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { isRepairableTenantDataPlaneError } from '@deepline/ingestion-v2/tenant-data-plane-errors';
|
|
3
|
+
import {
|
|
4
|
+
MONITOR_REFUND_SETTLEMENT_PENDING_CODE,
|
|
5
|
+
PROVIDER_MONITOR_CONTROL_STATE_PENDING_CODE,
|
|
6
|
+
} from '@deepline/monitors/signal-radars/inbound-failure-codes';
|
|
3
7
|
import type { SignalRadarInboundMessage } from '@deepline/monitors/signal-radars/inbound-message';
|
|
8
|
+
import {
|
|
9
|
+
hasMonitorSdkValidationIssues,
|
|
10
|
+
MONITOR_SDK_VALIDATION_ERROR_CODE,
|
|
11
|
+
} from '@deepline/monitors/validation';
|
|
4
12
|
|
|
5
13
|
// Minimal pg client seam shared with the ingestion stack: a `query(sql, args)`
|
|
6
14
|
// that returns `{ rows }`. Deliberately structural so PGlite (tests) and the
|
|
@@ -38,7 +46,10 @@ export function classifyInboundFailure(error: unknown): InboundFailureClass {
|
|
|
38
46
|
: '';
|
|
39
47
|
const transientCodes = new Set([
|
|
40
48
|
'tenant_data_plane_repair_required',
|
|
41
|
-
|
|
49
|
+
// An admission-backed callback whose Convex binding has not landed yet.
|
|
50
|
+
PROVIDER_MONITOR_CONTROL_STATE_PENDING_CODE,
|
|
51
|
+
// A refund waits for its lifecycle charge, which settles on its own clock.
|
|
52
|
+
MONITOR_REFUND_SETTLEMENT_PENDING_CODE,
|
|
42
53
|
// The worker emits this after capture-first receipt persistence cannot be
|
|
43
54
|
// completed. The event has not entered durable storage, so it must remain
|
|
44
55
|
// retryable even after the ordinary poison-message delivery budget.
|
|
@@ -59,6 +70,9 @@ export function classifyInboundFailure(error: unknown): InboundFailureClass {
|
|
|
59
70
|
'EPIPE',
|
|
60
71
|
'ENOTFOUND',
|
|
61
72
|
'EAI_AGAIN',
|
|
73
|
+
// `snitcher_ip2company_quota_exceeded` is left out on purpose: a spent
|
|
74
|
+
// quota will not recover inside the retry budget, so that event dead-letters
|
|
75
|
+
// with its payload retained and waits for a redrive.
|
|
62
76
|
'snitcher_ip2company_retryable',
|
|
63
77
|
'57P01', // admin shutdown
|
|
64
78
|
'57P02', // crash shutdown
|
|
@@ -73,8 +87,28 @@ export function classifyInboundFailure(error: unknown): InboundFailureClass {
|
|
|
73
87
|
]);
|
|
74
88
|
if (code && transientCodes.has(code)) return 'transient';
|
|
75
89
|
|
|
90
|
+
// A lifecycle fence is temporary contention, including while recording a
|
|
91
|
+
// billing suspension. Preserve the callback until its owner finishes; do
|
|
92
|
+
// not classify unrelated validation failures as retryable.
|
|
93
|
+
if (
|
|
94
|
+
code === MONITOR_SDK_VALIDATION_ERROR_CODE &&
|
|
95
|
+
hasMonitorSdkValidationIssues(error) &&
|
|
96
|
+
error.issues.length > 0 &&
|
|
97
|
+
error.issues.every(
|
|
98
|
+
(issue) =>
|
|
99
|
+
issue?.code === 'provider_monitor_operation_in_progress' ||
|
|
100
|
+
issue?.code === 'provider_monitor_delete_in_progress',
|
|
101
|
+
)
|
|
102
|
+
) {
|
|
103
|
+
return 'transient';
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
const message = errorMessage(error);
|
|
77
107
|
const transientPatterns = [
|
|
108
|
+
// pg reports subsequent operations on a client whose connection failed
|
|
109
|
+
// without retaining the original socket error's code. A fresh delivery
|
|
110
|
+
// acquires a usable client; this is infrastructure failure, not poison.
|
|
111
|
+
/client has encountered a connection error and is not queryable/i,
|
|
78
112
|
/connection (?:terminated|refused|reset|closed|failure)/i,
|
|
79
113
|
/could not connect to server/i,
|
|
80
114
|
/connection to server .* failed/i,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Failure codes shared by whoever raises an inbound failure and whoever decides
|
|
2
|
+
// what to do about it. A literal on each side drifted once (KAR-74), so a
|
|
3
|
+
// retryable failure read as poison and dead-lettered. Convex imports this file,
|
|
4
|
+
// so it holds constants only.
|
|
5
|
+
|
|
6
|
+
/** An admission-backed callback whose Convex monitor binding has not landed. */
|
|
7
|
+
export const PROVIDER_MONITOR_CONTROL_STATE_PENDING_CODE =
|
|
8
|
+
'provider_monitor_control_state_pending';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A callback for a retired binding of a monitor that still exists: a replaced
|
|
12
|
+
* radar, a finished rotation or a suspension. Permanent on purpose. It can never
|
|
13
|
+
* resolve, so it dead-letters on its budget and the row keeps the payload.
|
|
14
|
+
*/
|
|
15
|
+
export const PROVIDER_CALLBACK_BINDING_RETIRED_CODE =
|
|
16
|
+
'provider_callback_binding_retired';
|
|
17
|
+
|
|
18
|
+
/** A refund waiting for its lifecycle charge to settle. */
|
|
19
|
+
export const MONITOR_REFUND_SETTLEMENT_PENDING_CODE =
|
|
20
|
+
'monitor_refund_settlement_pending';
|
|
21
|
+
|
|
22
|
+
/** Storage has no blob for this receipt. No retry can bring it back. */
|
|
23
|
+
export const SIGNAL_RADAR_INBOUND_PAYLOAD_MISSING_CODE =
|
|
24
|
+
'signal_radar_inbound_payload_missing';
|