dirigent-server 0.23.4__tar.gz → 0.25.0__tar.gz
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.
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/PKG-INFO +5 -5
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/pyproject.toml +5 -5
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/pyproject.toml.orig +5 -5
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/app.py +6 -2
- dirigent_server-0.25.0/src/dirigent_server/bodies.py +21 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/__init__.py +15 -2
- dirigent_server-0.25.0/src/dirigent_server/routes/endpoints.py +87 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/hooks.py +2 -19
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/pipelines.py +4 -1
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/runs.py +6 -2
- dirigent_server-0.25.0/src/dirigent_server/routes/sources.py +164 -0
- dirigent_server-0.23.4/src/dirigent_server/static/assets/AdminOnly-CtBdW1t6.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/AdminOnly-Dqm_HMca.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Alerting-Bly3dwDA.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Alerting-D6pqigdf.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Blocks-mwir1kMn.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Blocks-Bytmt1fM.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Breadcrumb-CPpwoVR5.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Breadcrumb-B2IR8GK2.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/ConnectionFields-D3fXP9cK.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/ConnectionFields-G7W5qJwZ.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Connections-BVkbKzgv.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Connections-BpxNTEtq.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Dashboard-rNibBU5n.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Dashboard-yg_PfN2g.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Disclosure-C-OLxsgl.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Disclosure-C9L_xX_J.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/ExamplePanel-DiOC2XzU.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/ExamplePanel-BeqB5msH.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Examples-CeZzJLWE.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Examples-wkgoAzZq.js +2 -2
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Instant-Ogv9qDZy.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Instant-D6i01hcr.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/JsonBlock-Cf5e31G4.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/JsonBlock-DgwmVqGz.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/ListTable-BOX3h68A.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/ListTable-DSWyvb8k.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Overview-BLQuBe3V.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Overview-CnGL0wjw.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/PageState-859W4wWp.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/PageState-DF9ivqbc.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Panel-Hp0TZRIS.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Panel-DTQJa1sZ.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Picker-LdVHV90h.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Picker-Cgo9nW0b.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/PipelineEditor-bF09rBH9.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/PipelineEditor-D5olks3D.js +2 -2
- dirigent_server-0.23.4/src/dirigent_server/static/assets/PipelineGraph-DLUkce2A.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/PipelineGraph-DwsuiUEd.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/PipelinePreview-CoTL16Me.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/PipelinePreview-C_TcCIsN.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/PipelineTab-DTiGWUlM.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/PipelineTab-D39HrVFX.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/ProgramReference-XGlt7u1Z.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/ProgramReference-B3uA-mPM.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Refusal-DGmDdSgN.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Refusal-BG1VLLIm.js +1 -1
- dirigent_server-0.25.0/src/dirigent_server/static/assets/RunDetail-Bx206nJ4.js +3 -0
- dirigent_server-0.23.4/src/dirigent_server/static/assets/RunGraph-DwutZGHY.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/RunGraph-BYq35Slz.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/SchemaForm-uac9aORz.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/SchemaForm-BmQZtkI_.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Schemas-DUzFgJ9A.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Schemas-Dn_synyK.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/SettingsDialog-CtKKIyQW.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/SettingsDialog-QWlfP4dD.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/StarterPicker-CnOJ9l5T.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/StarterPicker-C6lX7LfD.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/StepPorts-BQlpO46o.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/StepPorts-jJA5aDQP.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/TileCard-CsEa_IEK.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/TileCard-uG_zwie0.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Triggers-CeTfFQ6H.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Triggers-Cu3_jlHI.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Users-CkLuwS-8.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Users-CXJF5mGi.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/WindowedPane-Bil9u7rQ.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/WindowedPane-CXFu5mlc.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/Workers-BFzmiHov.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/Workers-jZ6NAW6o.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/WorkersTable-kELfLGCN.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/WorkersTable-CD0L_wxZ.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/api-jh39Ky4Q.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/api-DJNHhjXE.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/auth-Bdybp9f_.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/auth-B7r6W6Vu.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/badge-Eu1xPQ-u.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/badge-IW-Km0ZR.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/blocks-B8eZqUob.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/blocks-CrBoMbKP.js +1 -1
- dirigent_server-0.25.0/src/dirigent_server/static/assets/chevron-down-enAbsfFc.js +1 -0
- dirigent_server-0.23.4/src/dirigent_server/static/assets/connections-DobzdyIe.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/connections-DDZFssUk.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/copy-CwsIH1zY.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/copy-awkkciuD.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/dropdown-menu-fVWTjkXO.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/dropdown-menu-D4HkNlfx.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/examples-BP1UpQbc.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/examples-Cm8vEB1c.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/file-braces-D0GrrmLo.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/file-braces--X3RovPP.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/format-DK4FnJoS.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/format-DdvSSWfL.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/glyphs-DLSRr36C.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/glyphs-D25qU4O_.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/index-C5xO5XtZ.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/index-Gmw0E_GE.js +3 -3
- dirigent_server-0.23.4/src/dirigent_server/static/assets/input-DjAM-vmX.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/input-jjCkDOZp.js +1 -1
- dirigent_server-0.25.0/src/dirigent_server/static/assets/labels-EiQNiH0M.js +1 -0
- dirigent_server-0.23.4/src/dirigent_server/static/assets/nav-Dr9UOjZp.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/nav-DtSZ6P7U.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/paging-B8nfgCnQ.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/paging-CiW3H56p.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/pipelines-CFguQTLF.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/pipelines-BnHP4Ayn.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/play-lh-2vSaT.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/play-B39ODKcJ.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/resolveAriaLabelledBy-gVlixxhm.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/resolveAriaLabelledBy-DM2-IMUt.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/schemas-DcjLLg6l.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/schemas-CqXQbfPV.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/status-Didq7MpX.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/status-BCNzBc7c.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/tooltip-CrzRgh7Y.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/tooltip-Ctqs1ee8.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/triggers-DM2qTKEm.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/triggers-CDY1mIMb.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/users-Cu33sW4_.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/users-Doy6ivrv.js +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/workers-DzwKP3Ua.js → dirigent_server-0.25.0/src/dirigent_server/static/assets/workers-BbyGGyp4.js +1 -1
- dirigent_server-0.25.0/src/dirigent_server/static/assets/x-DyZorXwS.js +1 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/index.html +19 -19
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/ui.py +1 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/RunDetail-BUvuMTta.js +0 -3
- dirigent_server-0.23.4/src/dirigent_server/static/assets/chevron-down-P-YdU4_3.js +0 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/labels-DPg21HPJ.js +0 -1
- dirigent_server-0.23.4/src/dirigent_server/static/assets/x-CfN8vp59.js +0 -1
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/LICENSE +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/README.md +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/THIRD_PARTY_NOTICES.md +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/__init__.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/dependencies.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/errors.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/health.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/logging.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/messages.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/pagination.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/py.typed +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/alerts.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/auth.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/blocks.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/connections.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/examples.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/labels.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/playground.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/schema.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/schemas.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/system.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/trigger_documents.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/triggers.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/users.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/routes/workers.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/security.py +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/.gitkeep +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/CodeEditor-BJ3F4VVc.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/CodeEditor-C4OnjBMt.css +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/Description-6wohd6-Q.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/KindChip-CwU_Xxdy.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/Mark-DQR2php6.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/Markdown-BOo7co1-.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/Segmented-KaDiGiyr.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/chunk-OB3PAWPO-B79niu4V.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/codicon-DCmgc-ay.ttf +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/dist-CvOdB3Md.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/docs-CCoB3shg.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/editor.worker-CIvRzd4O.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/elk-engine-Bm7I_NRI.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/elk-worker.min-DfmSo98M.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-cyrillic-ext-wght-normal-d45eAU9y.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-cyrillic-wght-normal-BAAhND-U.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-greek-wght-normal-CmyJS8uq.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-latin-ext-wght-normal-CIII54If.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-latin-wght-normal-IvpUvPa2.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/ibm-plex-sans-vietnamese-wght-normal-Dg1JeJN0.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/identity-BNZxCf_y.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/idle-DnO3aHK7.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/index-DZ7D7u3R.css +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2 +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/json.worker-fczZDBja.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/jsonMode-BVXlQ0c3.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/panels-D1Fnei43.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/preferences-SNZNX5Se.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/preload-helper-DjzSQ1t3.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/rolldown-runtime-Dd_uD5pT.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/shell-CC2rA5mh.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/sql-NEE52Syq.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/starters-DexsdOaG.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/store-D-5yFBN1.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/textarea-D86x5ut1.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/twig-De2hgUGE.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/use-heartbeat-C3WWagro.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/use-store-CZcp6jmY.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/utils-CT7ZGLfR.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/yaml-BIVCD_dG.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/assets/yaml.worker-Rk6p-jPU.js +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/favicon-32.png +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/static/logo.png +0 -0
- {dirigent_server-0.23.4 → dirigent_server-0.25.0}/src/dirigent_server/transactions.py +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dirigent-server
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Dirigent FastAPI server: the REST API, its authentication, and the health probes.
|
|
5
5
|
License-Expression: LicenseRef-Proprietary
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
License-File: THIRD_PARTY_NOTICES.md
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
-
Requires-Dist: dirigent-client==0.
|
|
11
|
-
Requires-Dist: dirigent-common==0.
|
|
12
|
-
Requires-Dist: dirigent-core==0.
|
|
13
|
-
Requires-Dist: dirigent-examples==0.
|
|
10
|
+
Requires-Dist: dirigent-client==0.25.0
|
|
11
|
+
Requires-Dist: dirigent-common==0.25.0
|
|
12
|
+
Requires-Dist: dirigent-core==0.25.0
|
|
13
|
+
Requires-Dist: dirigent-examples==0.25.0
|
|
14
14
|
Requires-Dist: fastapi>=0.142.2
|
|
15
15
|
Requires-Python: >=3.13
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-server"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
description = "Dirigent FastAPI server: the REST API, its authentication, and the health probes."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -14,10 +14,10 @@ classifiers = [
|
|
|
14
14
|
"Programming Language :: Python :: 3.13",
|
|
15
15
|
]
|
|
16
16
|
dependencies = [
|
|
17
|
-
"dirigent-client==0.
|
|
18
|
-
"dirigent-common==0.
|
|
19
|
-
"dirigent-core==0.
|
|
20
|
-
"dirigent-examples==0.
|
|
17
|
+
"dirigent-client==0.25.0",
|
|
18
|
+
"dirigent-common==0.25.0",
|
|
19
|
+
"dirigent-core==0.25.0",
|
|
20
|
+
"dirigent-examples==0.25.0",
|
|
21
21
|
"fastapi>=0.142.2",
|
|
22
22
|
]
|
|
23
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-server"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
description = "Dirigent FastAPI server: the REST API, its authentication, and the health probes."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -11,10 +11,10 @@ classifiers = [
|
|
|
11
11
|
"Programming Language :: Python :: 3.13",
|
|
12
12
|
]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"dirigent-client==0.
|
|
15
|
-
"dirigent-common==0.
|
|
16
|
-
"dirigent-core==0.
|
|
17
|
-
"dirigent-examples==0.
|
|
14
|
+
"dirigent-client==0.25.0",
|
|
15
|
+
"dirigent-common==0.25.0",
|
|
16
|
+
"dirigent-core==0.25.0",
|
|
17
|
+
"dirigent-examples==0.25.0",
|
|
18
18
|
"fastapi>=0.142.2",
|
|
19
19
|
]
|
|
20
20
|
|
|
@@ -15,12 +15,13 @@ from dirigent_core.directory import apply_directory
|
|
|
15
15
|
from dirigent_core.engine.services import EngineServices
|
|
16
16
|
from dirigent_core.plugins import PluginHost, load_plugin_host
|
|
17
17
|
from dirigent_core.scheduler import Scheduler
|
|
18
|
+
from dirigent_core.sources.intake import Intake
|
|
18
19
|
from dirigent_core.telemetry import configure_telemetry, instrument_fastapi
|
|
19
20
|
from dirigent_server.errors import install_error_handlers
|
|
20
21
|
from dirigent_server.health import build_registry
|
|
21
22
|
from dirigent_server.health import router as health_router
|
|
22
23
|
from dirigent_server.logging import get_logger
|
|
23
|
-
from dirigent_server.routes import TAGS, build_hooks_router, build_router
|
|
24
|
+
from dirigent_server.routes import TAGS, build_endpoints_router, build_hooks_router, build_router
|
|
24
25
|
from dirigent_server.security import install_cross_site_guard
|
|
25
26
|
from dirigent_server.ui import mount_ui_assets, mount_ui_shell
|
|
26
27
|
|
|
@@ -32,7 +33,8 @@ Every endpoint under `/api/v1` requires authentication: a bearer token for autom
|
|
|
32
33
|
the session cookie `POST /api/v1/auth/login` sets for a browser. The probes under `/health`,
|
|
33
34
|
this document itself, and the playground under `/api/v1/playground` are the exceptions.
|
|
34
35
|
`POST /hooks/{token}` is outside the versioned API and authenticates with its own
|
|
35
|
-
per-trigger token
|
|
36
|
+
per-trigger token, and so is every route under `/endpoints`, which a pipeline's endpoint
|
|
37
|
+
sources declare and which authenticates with each source's own token.
|
|
36
38
|
|
|
37
39
|
The playground serves generated data and chosen behaviour to documents that need something
|
|
38
40
|
to happen: it needs no credential, opens no database session, and reads no instance data.
|
|
@@ -108,12 +110,14 @@ def create_app(
|
|
|
108
110
|
app.state.settings = resolved
|
|
109
111
|
app.state.version = __version__
|
|
110
112
|
app.state.services = EngineServices.build(resolved, host or load_plugin_host())
|
|
113
|
+
app.state.intake = Intake()
|
|
111
114
|
install_cross_site_guard(app, resolved)
|
|
112
115
|
install_error_handlers(app)
|
|
113
116
|
mount_ui_assets(app, resolved)
|
|
114
117
|
app.include_router(health_router)
|
|
115
118
|
app.include_router(build_hooks_router())
|
|
116
119
|
app.include_router(build_router(resolved), prefix=resolved.api_prefix)
|
|
120
|
+
app.include_router(build_endpoints_router(), prefix=resolved.endpoint_prefix)
|
|
117
121
|
mount_ui_shell(app, resolved)
|
|
118
122
|
instrument_fastapi(app)
|
|
119
123
|
return app
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Reading a request's body under a cap, for the routes a stranger may call."""
|
|
2
|
+
|
|
3
|
+
from fastapi import Request
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def read_capped(request: Request, limit: int) -> bytes:
|
|
7
|
+
"""Read the body, stopping one byte past the limit rather than after all of it.
|
|
8
|
+
|
|
9
|
+
``request.body()`` buffers whatever arrives before the size can be checked, so an
|
|
10
|
+
unauthenticated caller could make the process allocate a gigabyte to be told a megabyte
|
|
11
|
+
is the maximum. What comes back may be longer than the limit, which is how a caller
|
|
12
|
+
learns the body was too large.
|
|
13
|
+
"""
|
|
14
|
+
chunks: list[bytes] = []
|
|
15
|
+
size = 0
|
|
16
|
+
async for chunk in request.stream():
|
|
17
|
+
chunks.append(chunk)
|
|
18
|
+
size += len(chunk)
|
|
19
|
+
if size > limit:
|
|
20
|
+
break
|
|
21
|
+
return b"".join(chunks)
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Every business router is mounted behind :func:`require_principal`, so authentication is a
|
|
4
4
|
property of the mount. Only login is exempt. Webhook intake authenticates as the trigger
|
|
5
|
-
rather than as a person, so it is mounted at the application root instead
|
|
5
|
+
rather than as a person, so it is mounted at the application root instead, and endpoint
|
|
6
|
+
intake, which authenticates as the source, is mounted under the endpoint prefix.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
from fastapi import APIRouter, Depends
|
|
@@ -13,6 +14,7 @@ from dirigent_server.routes import (
|
|
|
13
14
|
auth,
|
|
14
15
|
blocks,
|
|
15
16
|
connections,
|
|
17
|
+
endpoints,
|
|
16
18
|
examples,
|
|
17
19
|
hooks,
|
|
18
20
|
labels,
|
|
@@ -21,6 +23,7 @@ from dirigent_server.routes import (
|
|
|
21
23
|
runs,
|
|
22
24
|
schema,
|
|
23
25
|
schemas,
|
|
26
|
+
sources,
|
|
24
27
|
system,
|
|
25
28
|
trigger_documents,
|
|
26
29
|
triggers,
|
|
@@ -37,6 +40,8 @@ TAGS: list[dict[str, str]] = [
|
|
|
37
40
|
{"name": "triggers", "description": "A pipeline's schedules and inbound webhooks."},
|
|
38
41
|
{"name": "alerts", "description": "Alert rules, and the queue they deliver through."},
|
|
39
42
|
{"name": "hooks", "description": "Webhook intake, authenticated by its own token."},
|
|
43
|
+
{"name": "endpoints", "description": "Endpoint sources, each authenticated by its own token."},
|
|
44
|
+
{"name": "sources", "description": "Where a pipeline's inputs enter, and what has arrived."},
|
|
40
45
|
{"name": "connections", "description": "Named credential records of contributed kinds."},
|
|
41
46
|
{"name": "blocks", "description": "The catalog every plugin contributes to."},
|
|
42
47
|
{"name": "labels", "description": "The wording every installed pack refuses in."},
|
|
@@ -70,6 +75,7 @@ def build_router(settings: Settings | None = None) -> APIRouter:
|
|
|
70
75
|
pipelines,
|
|
71
76
|
triggers,
|
|
72
77
|
trigger_documents,
|
|
78
|
+
sources,
|
|
73
79
|
runs,
|
|
74
80
|
alerts,
|
|
75
81
|
connections,
|
|
@@ -87,6 +93,13 @@ def build_router(settings: Settings | None = None) -> APIRouter:
|
|
|
87
93
|
return router
|
|
88
94
|
|
|
89
95
|
|
|
96
|
+
def build_endpoints_router() -> APIRouter:
|
|
97
|
+
"""Assemble the endpoint intake, mounted under the instance's endpoint prefix."""
|
|
98
|
+
router = APIRouter(route_class=Transactional)
|
|
99
|
+
router.include_router(endpoints.router)
|
|
100
|
+
return router
|
|
101
|
+
|
|
102
|
+
|
|
90
103
|
def build_hooks_router() -> APIRouter:
|
|
91
104
|
"""Assemble the unauthenticated webhook intake, mounted at the application root."""
|
|
92
105
|
router = APIRouter(route_class=Transactional)
|
|
@@ -94,4 +107,4 @@ def build_hooks_router() -> APIRouter:
|
|
|
94
107
|
return router
|
|
95
108
|
|
|
96
109
|
|
|
97
|
-
__all__ = ["TAGS", "build_hooks_router", "build_router"]
|
|
110
|
+
__all__ = ["TAGS", "build_endpoints_router", "build_hooks_router", "build_router"]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Endpoint intake: the routes a pipeline's endpoint sources declare, under the instance's endpoint prefix.
|
|
2
|
+
|
|
3
|
+
Mounted outside ``/api/v1``, which requires a principal as a property of the mount: a call to
|
|
4
|
+
an endpoint authenticates with the token its source was given, or with nothing for a source
|
|
5
|
+
that writes out ``public``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from fastapi import APIRouter, Request, Response, status
|
|
9
|
+
from fastapi.responses import JSONResponse
|
|
10
|
+
|
|
11
|
+
from dirigent_client.schemas import InputAccepted
|
|
12
|
+
from dirigent_core.sources.intake import Call, Ignore, Intake, Refusal, lowered
|
|
13
|
+
from dirigent_server.bodies import read_capped
|
|
14
|
+
from dirigent_server.dependencies import ServicesDep, SessionDep
|
|
15
|
+
from dirigent_server.errors import answer, render
|
|
16
|
+
from dirigent_server.transactions import Transactional
|
|
17
|
+
|
|
18
|
+
router = APIRouter(route_class=Transactional, tags=["endpoints"])
|
|
19
|
+
|
|
20
|
+
#: The methods a received source may declare, which is every method this route takes.
|
|
21
|
+
METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
#: Every answer an endpoint gives, in the order its checks are made.
|
|
25
|
+
RESPONSES: dict[int | str, dict[str, object]] = {
|
|
26
|
+
202: {"description": "The input became a run; the body says where to read it."},
|
|
27
|
+
204: {"description": "The input was a sign of life, such as a handshake, and started no run."},
|
|
28
|
+
400: {"description": "The body is not what its content type says."},
|
|
29
|
+
401: {"description": "The source takes a bearer token, and the one presented is not its own."},
|
|
30
|
+
404: {"description": "No source answers this path."},
|
|
31
|
+
405: {"description": "A source answers this path, but not with this method."},
|
|
32
|
+
409: {"description": "The pipeline's concurrency policy, or the run itself, refused the input."},
|
|
33
|
+
413: {"description": "The body is larger than the source reads."},
|
|
34
|
+
415: {"description": "The source does not take this content type."},
|
|
35
|
+
429: {"description": "The instance or the source is taking calls faster than its rate."},
|
|
36
|
+
503: {"description": "The source or its pipeline is paused, or as many of its runs are in flight as it allows."},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def intake_of(request: Request) -> Intake:
|
|
41
|
+
"""Return this process's intake: its routes as last read, and its buckets."""
|
|
42
|
+
intake: Intake = request.app.state.intake
|
|
43
|
+
return intake
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def call_endpoint(path: str, request: Request, session: SessionDep, services: ServicesDep) -> Response:
|
|
47
|
+
"""Turn one call into a run of the pipeline whose source answers it, or refuse it with why."""
|
|
48
|
+
call = Call(
|
|
49
|
+
method=request.method,
|
|
50
|
+
path=f"/{path}",
|
|
51
|
+
query=request.query_params.multi_items(),
|
|
52
|
+
headers=lowered(request.headers.items()),
|
|
53
|
+
caller=request.client.host if request.client else None,
|
|
54
|
+
)
|
|
55
|
+
taken = await intake_of(request).take(session, services, call, lambda limit: read_capped(request, limit))
|
|
56
|
+
if isinstance(taken, Ignore):
|
|
57
|
+
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
|
58
|
+
if isinstance(taken, Refusal):
|
|
59
|
+
return _refused(request, taken)
|
|
60
|
+
return JSONResponse(
|
|
61
|
+
status_code=status.HTTP_202_ACCEPTED,
|
|
62
|
+
content=taken.model_dump(mode="json"),
|
|
63
|
+
headers={"Location": taken.run_url},
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
for _method in METHODS:
|
|
68
|
+
router.add_api_route(
|
|
69
|
+
"/{path:path}",
|
|
70
|
+
call_endpoint,
|
|
71
|
+
methods=[_method],
|
|
72
|
+
operation_id=f"callEndpoint{_method.title()}",
|
|
73
|
+
summary=f"Call an endpoint source with {_method}",
|
|
74
|
+
status_code=status.HTTP_202_ACCEPTED,
|
|
75
|
+
response_model=InputAccepted,
|
|
76
|
+
responses=RESPONSES,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _refused(request: Request, refusal: Refusal) -> Response:
|
|
81
|
+
"""Answer a refusal in the one problem shape, with any header it has to set."""
|
|
82
|
+
problem = render(
|
|
83
|
+
refusal.status, refusal.message, code=refusal.code, params=refusal.params, instance=request.url.path
|
|
84
|
+
)
|
|
85
|
+
response = answer(problem)
|
|
86
|
+
response.headers.update(refusal.headers)
|
|
87
|
+
return response
|
|
@@ -13,6 +13,7 @@ from dirigent_client.schemas import HookAccepted
|
|
|
13
13
|
from dirigent_core.ratelimit import TokenBucket
|
|
14
14
|
from dirigent_core.triggers import SIGNATURE_HEADER, deliver, resolve_webhook
|
|
15
15
|
from dirigent_core.triggers.webhooks import UNKNOWN_TOKEN, hash_token
|
|
16
|
+
from dirigent_server.bodies import read_capped
|
|
16
17
|
from dirigent_server.dependencies import ServicesDep, SessionDep
|
|
17
18
|
from dirigent_server.logging import get_logger
|
|
18
19
|
from dirigent_server.transactions import Transactional
|
|
@@ -81,7 +82,7 @@ async def deliver_hook(
|
|
|
81
82
|
session,
|
|
82
83
|
services,
|
|
83
84
|
webhook,
|
|
84
|
-
body=await
|
|
85
|
+
body=await read_capped(request, services.settings.webhook_max_payload),
|
|
85
86
|
signature=signature,
|
|
86
87
|
source=request.client.host if request.client else None,
|
|
87
88
|
)
|
|
@@ -94,21 +95,3 @@ def _throttled(response: Response, detail: str) -> HookAccepted:
|
|
|
94
95
|
response.status_code = status.HTTP_429_TOO_MANY_REQUESTS
|
|
95
96
|
response.headers["Retry-After"] = "60"
|
|
96
97
|
return HookAccepted(outcome=WebhookOutcome.REJECTED, detail=detail)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
async def _read_body(request: Request, *, limit: int) -> bytes:
|
|
100
|
-
"""Read the body, stopping one byte past the limit rather than after all of it.
|
|
101
|
-
|
|
102
|
-
``request.body()`` buffers whatever arrives before the size can be checked, so an
|
|
103
|
-
unauthenticated caller could make the process allocate a gigabyte to be told a megabyte
|
|
104
|
-
is the maximum. What comes back goes to the ordinary refusal path, so an oversized
|
|
105
|
-
delivery is still recorded in the history.
|
|
106
|
-
"""
|
|
107
|
-
chunks: list[bytes] = []
|
|
108
|
-
size = 0
|
|
109
|
-
async for chunk in request.stream():
|
|
110
|
-
chunks.append(chunk)
|
|
111
|
-
size += len(chunk)
|
|
112
|
-
if size > limit:
|
|
113
|
-
break
|
|
114
|
-
return b"".join(chunks)
|
|
@@ -30,7 +30,7 @@ from dirigent_core.engine.definition import load_definition
|
|
|
30
30
|
from dirigent_core.engine.runs import Provenance, RunWindow
|
|
31
31
|
from dirigent_core.engine.services import EngineServices
|
|
32
32
|
from dirigent_core.messages import PIPELINE_DEACTIVATED, PIPELINE_NO_VERSIONS
|
|
33
|
-
from dirigent_core.models import Pipeline
|
|
33
|
+
from dirigent_core.models import Pipeline, utcnow
|
|
34
34
|
from dirigent_core.pipelines import (
|
|
35
35
|
NO_COUNTS,
|
|
36
36
|
PipelineCounts,
|
|
@@ -46,6 +46,7 @@ from dirigent_core.pipelines import (
|
|
|
46
46
|
revalidate,
|
|
47
47
|
set_active,
|
|
48
48
|
)
|
|
49
|
+
from dirigent_core.sources.entries import hand_entry
|
|
49
50
|
from dirigent_core.triggers.backfill import backfill
|
|
50
51
|
from dirigent_core.triggers.schedules import UnknownSchedule, find_schedule
|
|
51
52
|
from dirigent_server.dependencies import ServicesDep, SessionDep
|
|
@@ -304,11 +305,13 @@ async def start_run(
|
|
|
304
305
|
version = await get_version(session, pipeline)
|
|
305
306
|
definition = load_definition(version.document)
|
|
306
307
|
definition.validate_params(payload.params, services.format_checker)
|
|
308
|
+
entry = hand_entry(definition, services.sources, payload.source, payload.input, received_at=utcnow())
|
|
307
309
|
run = await create_run(
|
|
308
310
|
session,
|
|
309
311
|
services,
|
|
310
312
|
version,
|
|
311
313
|
params=payload.params,
|
|
314
|
+
entry=entry,
|
|
312
315
|
attribution=Attribution(
|
|
313
316
|
kind=principal.trigger_kind,
|
|
314
317
|
id=principal.token_id or principal.user_id,
|
|
@@ -35,7 +35,7 @@ from dirigent_core.artifacts import JSON_CONTENT_TYPE, TEXT_KEY, canonical_json,
|
|
|
35
35
|
from dirigent_core.database import session_scope
|
|
36
36
|
from dirigent_core.engine.definition import PipelineDefinition, load_definition
|
|
37
37
|
from dirigent_core.engine.runs import cancel_run, retry_step
|
|
38
|
-
from dirigent_core.engine.state import StepCounts, attempt_counts, item_counts, step_states
|
|
38
|
+
from dirigent_core.engine.state import StepCounts, attempt_counts, item_counts, item_wise_parent, step_states
|
|
39
39
|
from dirigent_core.messages import CANCELLED_BY
|
|
40
40
|
from dirigent_core.models import (
|
|
41
41
|
ArtifactRef,
|
|
@@ -122,7 +122,9 @@ def _render_run(run: Run, pipeline: Pipeline, version: PipelineVersion, failed:
|
|
|
122
122
|
params=dict(run.params),
|
|
123
123
|
triggered_by_kind=run.triggered_by_kind,
|
|
124
124
|
parent_run_id=run.triggered_by_id if run.triggered_by_kind is TriggerKind.PIPELINE else None,
|
|
125
|
+
triggered_by_id=run.triggered_by_id,
|
|
125
126
|
triggered_by_label=run.triggered_by_label,
|
|
127
|
+
source=run.source_step,
|
|
126
128
|
trace_id=telemetry.trace_id_of(run.traceparent),
|
|
127
129
|
error=run.error or (failed.error if failed is not None else None),
|
|
128
130
|
error_code=run.error_code or (failed.code if failed is not None else None),
|
|
@@ -160,12 +162,14 @@ def _dag(
|
|
|
160
162
|
DagNode(
|
|
161
163
|
code=name,
|
|
162
164
|
name=step.name,
|
|
163
|
-
|
|
165
|
+
kind=step.kind,
|
|
166
|
+
block=step.block_id,
|
|
164
167
|
outcome=states[name].outcome.value,
|
|
165
168
|
depends_on=list(step.depends_on),
|
|
166
169
|
rule=step.rule.value,
|
|
167
170
|
fan_out=step.is_fan_out,
|
|
168
171
|
grid_source=definition.grid_source(name),
|
|
172
|
+
item_wise_parent=item_wise_parent(definition, name),
|
|
169
173
|
items_total=sum(of_step.values()),
|
|
170
174
|
items_failed=of_step.get(RunItemStatus.FAILED, 0),
|
|
171
175
|
attempts=attempts[name].total if name in attempts else 0,
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""A pipeline's sources: what each listens to, its state, what has arrived, and what an operator does to it.
|
|
2
|
+
|
|
3
|
+
The instance keeps only the hash of a source's token, so the token is readable exactly once:
|
|
4
|
+
when an apply mints it, or when it is rotated.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
|
|
9
|
+
from fastapi import APIRouter
|
|
10
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
11
|
+
|
|
12
|
+
from dirigent_client.schemas import Page, SourceInputOut, SourceOut, SourceTokenOut
|
|
13
|
+
from dirigent_core.engine.services import EngineServices
|
|
14
|
+
from dirigent_core.models import Pipeline, Source
|
|
15
|
+
from dirigent_core.pipelines import require_pipeline
|
|
16
|
+
from dirigent_core.sources.rows import (
|
|
17
|
+
in_flight,
|
|
18
|
+
input_out,
|
|
19
|
+
list_inputs,
|
|
20
|
+
list_sources,
|
|
21
|
+
require_source,
|
|
22
|
+
rotate_source_token,
|
|
23
|
+
set_paused,
|
|
24
|
+
source_out,
|
|
25
|
+
)
|
|
26
|
+
from dirigent_server.dependencies import ServicesDep, SessionDep
|
|
27
|
+
from dirigent_server.pagination import DEFAULT_PAGE, AfterParam, LimitParam, clip, int_cursor, uuid_cursor
|
|
28
|
+
from dirigent_server.security import OperatorDep, PrincipalDep
|
|
29
|
+
from dirigent_server.transactions import Transactional
|
|
30
|
+
|
|
31
|
+
router = APIRouter(route_class=Transactional, tags=["sources"])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@router.get("/sources", operation_id="listSources", summary="List every source", response_model=Page[SourceOut])
|
|
35
|
+
async def list_all(
|
|
36
|
+
session: SessionDep,
|
|
37
|
+
services: ServicesDep,
|
|
38
|
+
principal: PrincipalDep,
|
|
39
|
+
after: AfterParam = None,
|
|
40
|
+
limit: LimitParam = DEFAULT_PAGE,
|
|
41
|
+
) -> Page[SourceOut]:
|
|
42
|
+
"""List every pipeline's sources, with their state and what they have taken, never their tokens."""
|
|
43
|
+
rows = await list_sources(session, after=uuid_cursor(after), limit=limit + 1)
|
|
44
|
+
return await _page(session, services, rows, limit)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@router.get(
|
|
48
|
+
"/pipelines/{code}/sources",
|
|
49
|
+
operation_id="listPipelineSources",
|
|
50
|
+
summary="List a pipeline's sources",
|
|
51
|
+
response_model=Page[SourceOut],
|
|
52
|
+
)
|
|
53
|
+
async def list_of_pipeline(
|
|
54
|
+
code: str,
|
|
55
|
+
session: SessionDep,
|
|
56
|
+
services: ServicesDep,
|
|
57
|
+
principal: PrincipalDep,
|
|
58
|
+
after: AfterParam = None,
|
|
59
|
+
limit: LimitParam = DEFAULT_PAGE,
|
|
60
|
+
) -> Page[SourceOut]:
|
|
61
|
+
"""List one pipeline's sources, with their state and what they have taken, never their tokens."""
|
|
62
|
+
pipeline = await require_pipeline(session, code)
|
|
63
|
+
rows = await list_sources(session, pipeline_id=pipeline.id, after=uuid_cursor(after), limit=limit + 1)
|
|
64
|
+
return await _page(session, services, rows, limit)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@router.get(
|
|
68
|
+
"/pipelines/{code}/sources/{source}",
|
|
69
|
+
operation_id="getSource",
|
|
70
|
+
summary="Read one source",
|
|
71
|
+
response_model=SourceOut,
|
|
72
|
+
)
|
|
73
|
+
async def get_source(
|
|
74
|
+
code: str, source: str, session: SessionDep, services: ServicesDep, principal: PrincipalDep
|
|
75
|
+
) -> SourceOut:
|
|
76
|
+
"""Read one source by its step code, never its token."""
|
|
77
|
+
pipeline = await require_pipeline(session, code)
|
|
78
|
+
row = await require_source(session, pipeline, source)
|
|
79
|
+
return await _one(session, services, row, pipeline)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@router.post(
|
|
83
|
+
"/pipelines/{code}/sources/{source}/$pause",
|
|
84
|
+
operation_id="pauseSource",
|
|
85
|
+
summary="Pause a source",
|
|
86
|
+
response_model=SourceOut,
|
|
87
|
+
)
|
|
88
|
+
async def pause(
|
|
89
|
+
code: str, source: str, session: SessionDep, services: ServicesDep, principal: OperatorDep
|
|
90
|
+
) -> SourceOut:
|
|
91
|
+
"""Refuse new inputs with 503, keeping the token and the counts; runs in flight carry on."""
|
|
92
|
+
pipeline = await require_pipeline(session, code)
|
|
93
|
+
row = await set_paused(session, pipeline, await require_source(session, pipeline, source), paused=True)
|
|
94
|
+
return await _one(session, services, row, pipeline)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@router.post(
|
|
98
|
+
"/pipelines/{code}/sources/{source}/$resume",
|
|
99
|
+
operation_id="resumeSource",
|
|
100
|
+
summary="Resume a source",
|
|
101
|
+
response_model=SourceOut,
|
|
102
|
+
)
|
|
103
|
+
async def resume(
|
|
104
|
+
code: str, source: str, session: SessionDep, services: ServicesDep, principal: OperatorDep
|
|
105
|
+
) -> SourceOut:
|
|
106
|
+
"""Take inputs again on the token that was already issued."""
|
|
107
|
+
pipeline = await require_pipeline(session, code)
|
|
108
|
+
row = await set_paused(session, pipeline, await require_source(session, pipeline, source), paused=False)
|
|
109
|
+
return await _one(session, services, row, pipeline)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@router.post(
|
|
113
|
+
"/pipelines/{code}/sources/{source}/$rotate-token",
|
|
114
|
+
operation_id="rotateSourceToken",
|
|
115
|
+
summary="Rotate a source's token",
|
|
116
|
+
response_model=SourceTokenOut,
|
|
117
|
+
)
|
|
118
|
+
async def rotate(
|
|
119
|
+
code: str, source: str, session: SessionDep, services: ServicesDep, principal: OperatorDep
|
|
120
|
+
) -> SourceTokenOut:
|
|
121
|
+
"""Mint a new token and forget the old one immediately; every caller has to be given it."""
|
|
122
|
+
pipeline = await require_pipeline(session, code)
|
|
123
|
+
row = await require_source(session, pipeline, source)
|
|
124
|
+
return await rotate_source_token(session, services.settings, services.sources, pipeline, row)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@router.get(
|
|
128
|
+
"/pipelines/{code}/sources/{source}/inputs",
|
|
129
|
+
operation_id="listSourceInputs",
|
|
130
|
+
summary="List a source's inputs",
|
|
131
|
+
response_model=Page[SourceInputOut],
|
|
132
|
+
)
|
|
133
|
+
async def inputs(
|
|
134
|
+
code: str,
|
|
135
|
+
source: str,
|
|
136
|
+
session: SessionDep,
|
|
137
|
+
principal: PrincipalDep,
|
|
138
|
+
after: AfterParam = None,
|
|
139
|
+
limit: LimitParam = DEFAULT_PAGE,
|
|
140
|
+
) -> Page[SourceInputOut]:
|
|
141
|
+
"""Read what has arrived, newest first, refusals included."""
|
|
142
|
+
pipeline = await require_pipeline(session, code)
|
|
143
|
+
row = await require_source(session, pipeline, source)
|
|
144
|
+
rows = await list_inputs(session, row.id, after=int_cursor(after), limit=limit + 1)
|
|
145
|
+
items, following = clip([input_out(entry) for entry in rows], limit, lambda entry: entry.id)
|
|
146
|
+
return Page(items=items, next=following)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
async def _one(session: AsyncSession, services: EngineServices, row: Source, pipeline: Pipeline) -> SourceOut:
|
|
150
|
+
"""Render one source with the runs it has unsettled."""
|
|
151
|
+
unsettled = (await in_flight(session, [row.id])).get(row.id, 0)
|
|
152
|
+
return source_out(services.settings, services.sources, row, pipeline, unsettled)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
async def _page(
|
|
156
|
+
session: AsyncSession, services: EngineServices, rows: Sequence[tuple[Source, Pipeline]], limit: int
|
|
157
|
+
) -> Page[SourceOut]:
|
|
158
|
+
"""Render a page of sources, counting what each has unsettled in one query."""
|
|
159
|
+
page, following = clip(list(rows), limit, lambda pair: pair[0].id)
|
|
160
|
+
counts = await in_flight(session, [row.id for row, _ in page])
|
|
161
|
+
items = [
|
|
162
|
+
source_out(services.settings, services.sources, row, pipeline, counts.get(row.id, 0)) for row, pipeline in page
|
|
163
|
+
]
|
|
164
|
+
return Page(items=items, next=following)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./labels-
|
|
1
|
+
import{t as e}from"./labels-EiQNiH0M.js";import{n as t}from"./PageState-DF9ivqbc.js";import{r as n}from"./utils-CT7ZGLfR.js";import{t as r}from"./use-store-CZcp6jmY.js";import{n as i,t as a}from"./auth-B7r6W6Vu.js";var o=n(),s={status:403,title:e.refusal.admin_only,code:`server.forbidden`,params:{},detail:e.refusal.shut,problems:[],instance:null};function c({children:e}){let n=r(a);return i(n)?(0,o.jsx)(o.Fragment,{children:e}):(0,o.jsx)(t,{loading:!1,problem:s,empty:!1,children:null})}export{c as t};
|