dirigent-client 0.26.0__tar.gz → 0.27.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.
Files changed (42) hide show
  1. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/PKG-INFO +2 -2
  2. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/pyproject.toml +2 -2
  3. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/pyproject.toml.orig +2 -2
  4. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/__init__.py +0 -14
  5. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/client.py +0 -6
  6. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/enums.py +14 -19
  7. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/sources.py +14 -2
  8. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/trigger_documents.py +2 -2
  9. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/__init__.py +2 -12
  10. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/pipelines.py +3 -25
  11. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/runs.py +1 -1
  12. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/sources.py +38 -7
  13. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/triggers.py +2 -114
  14. dirigent_client-0.26.0/src/dirigent_client/resources/watches.py +0 -29
  15. dirigent_client-0.26.0/src/dirigent_client/resources/webhooks.py +0 -80
  16. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/LICENSE +0 -0
  17. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/README.md +0 -0
  18. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/errors.py +0 -0
  19. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/messages.py +0 -0
  20. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/py.typed +0 -0
  21. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/__init__.py +0 -0
  22. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/alerts.py +0 -0
  23. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/auth.py +0 -0
  24. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/base.py +0 -0
  25. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/blocks.py +0 -0
  26. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/connections.py +0 -0
  27. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/examples.py +0 -0
  28. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/pipelines.py +0 -0
  29. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/runs.py +0 -0
  30. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/schedules.py +0 -0
  31. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/schemas.py +0 -0
  32. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/resources/system.py +0 -0
  33. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/alerts.py +0 -0
  34. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/auth.py +0 -0
  35. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/catalog.py +0 -0
  36. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/common.py +0 -0
  37. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/connections.py +0 -0
  38. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/examples.py +0 -0
  39. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/labels.py +0 -0
  40. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/schemas.py +0 -0
  41. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/schemas/system.py +0 -0
  42. {dirigent_client-0.26.0 → dirigent_client-0.27.0}/src/dirigent_client/transport.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-client
3
- Version: 0.26.0
3
+ Version: 0.27.0
4
4
  Summary: The dirigent API contract: typed wire schemas and an async Python client.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3.13
9
- Requires-Dist: dirigent-common==0.26.0
9
+ Requires-Dist: dirigent-common==0.27.0
10
10
  Requires-Dist: httpx2>=2.12.0
11
11
  Requires-Dist: pydantic>=2.13.5
12
12
  Requires-Dist: pyyaml>=6.0.3
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-client"
3
- version = "0.26.0"
3
+ version = "0.27.0"
4
4
  description = "The dirigent API contract: typed wire schemas and an async Python client."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,7 +11,7 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.26.0",
14
+ "dirigent-common==0.27.0",
15
15
  "httpx2>=2.12.0",
16
16
  "pydantic>=2.13.5",
17
17
  "pyyaml>=6.0.3",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-client"
3
- version = "0.26.0"
3
+ version = "0.27.0"
4
4
  description = "The dirigent API contract: typed wire schemas and an async Python client."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,7 +11,7 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.26.0",
14
+ "dirigent-common==0.27.0",
15
15
  "httpx2>=2.12.0",
16
16
  "pydantic>=2.13.5",
17
17
  "pyyaml>=6.0.3",
@@ -23,7 +23,6 @@ from dirigent_client.enums import (
23
23
  TokenKind,
24
24
  TriggerKind,
25
25
  UserRole,
26
- WebhookOutcome,
27
26
  WorkerStatus,
28
27
  )
29
28
  from dirigent_client.errors import (
@@ -68,14 +67,12 @@ from dirigent_client.schemas import (
68
67
  ConnectionUpdate,
69
68
  DagNode,
70
69
  DagView,
71
- DeliveryOut,
72
70
  DiffSummary,
73
71
  EndpointInput,
74
72
  ExampleDetail,
75
73
  ExampleOut,
76
74
  FiringOut,
77
75
  Health,
78
- HookAccepted,
79
76
  Identity,
80
77
  InputAccepted,
81
78
  IssuedTokenOut,
@@ -125,10 +122,6 @@ from dirigent_client.schemas import (
125
122
  UserIn,
126
123
  UserOut,
127
124
  ValidationIssue,
128
- WatchOut,
129
- WebhookIn,
130
- WebhookOut,
131
- WebhookTokenOut,
132
125
  WorkerOut,
133
126
  )
134
127
  from dirigent_client.transport import (
@@ -193,7 +186,6 @@ __all__ = [
193
186
  "DagNode",
194
187
  "DagView",
195
188
  "DocumentKind",
196
- "DeliveryOut",
197
189
  "DiffSummary",
198
190
  "ExampleDetail",
199
191
  "ExampleOut",
@@ -203,7 +195,6 @@ __all__ = [
203
195
  "FiringOutcome",
204
196
  "Forbidden",
205
197
  "Health",
206
- "HookAccepted",
207
198
  "Identity",
208
199
  "Importance",
209
200
  "IssuedTokenOut",
@@ -264,11 +255,6 @@ __all__ = [
264
255
  "ValidationFailed",
265
256
  "ValidationIssue",
266
257
  "WaitTimeout",
267
- "WebhookIn",
268
- "WebhookOut",
269
- "WebhookOutcome",
270
- "WatchOut",
271
- "WebhookTokenOut",
272
258
  "WorkerOut",
273
259
  "WorkerStatus",
274
260
  "declared_label",
@@ -19,8 +19,6 @@ from dirigent_client.resources.schemas import Schemas
19
19
  from dirigent_client.resources.sources import Sources
20
20
  from dirigent_client.resources.system import System, Workers
21
21
  from dirigent_client.resources.trigger_documents import TriggerDocuments
22
- from dirigent_client.resources.watches import Watches
23
- from dirigent_client.resources.webhooks import Webhooks
24
22
  from dirigent_client.transport import (
25
23
  API_PREFIX,
26
24
  DEFAULT_CONNECT_TIMEOUT,
@@ -65,8 +63,6 @@ class Dirigent:
65
63
  self.blocks = Blocks(self.transport)
66
64
  self.examples = Examples(self.transport)
67
65
  self.schedules = Schedules(self.transport)
68
- self.webhooks = Webhooks(self.transport)
69
- self.watches = Watches(self.transport)
70
66
  self.sources = Sources(self.transport)
71
67
  self.trigger_documents = TriggerDocuments(self.transport)
72
68
  self.alerts = Alerts(self.transport)
@@ -110,8 +106,6 @@ class BlockingDirigent:
110
106
  self.blocks = self.client.blocks
111
107
  self.examples = self.client.examples
112
108
  self.schedules = self.client.schedules
113
- self.webhooks = self.client.webhooks
114
- self.watches = self.client.watches
115
109
  self.sources = self.client.sources
116
110
  self.trigger_documents = self.client.trigger_documents
117
111
  self.alerts = self.client.alerts
@@ -103,7 +103,6 @@ class TriggerKind(StrEnum):
103
103
 
104
104
  ADHOC = "adhoc"
105
105
  SCHEDULE = "schedule"
106
- WEBHOOK = "webhook"
107
106
  API_TOKEN = "api_token"
108
107
  USER = "user"
109
108
  PIPELINE = "pipeline"
@@ -112,9 +111,6 @@ class TriggerKind(StrEnum):
112
111
  BACKFILL = "backfill"
113
112
  """A backfill over past windows created this one, and ``triggered_by_id`` names the schedule."""
114
113
 
115
- WATCH = "watch"
116
- """A watch armed this one to wait on its sensor, and ``triggered_by_id`` names the watch."""
117
-
118
114
  SOURCE = "source"
119
115
  """An input arrived at a source node, and ``triggered_by_id`` names the source."""
120
116
 
@@ -178,25 +174,18 @@ class FiringOutcome(StrEnum):
178
174
  """The run could not be created at all, and the reason is on the row."""
179
175
 
180
176
 
181
- class WebhookOutcome(StrEnum):
182
- """What the intake endpoint did with one delivery."""
183
-
184
- ACCEPTED = "accepted"
185
- """The payload mapped, validated, and started a run."""
186
-
187
- SKIPPED = "skipped"
188
- """The payload was good, but the pipeline's concurrency policy dropped the run."""
189
-
190
- REJECTED = "rejected"
191
- """The delivery was refused, and the reason is on the row."""
192
-
193
-
194
177
  class SourceState(StrEnum):
195
178
  """Whether a source takes inputs now, read from its row and the runs it has unsettled."""
196
179
 
180
+ STARTING = "starting"
181
+ """A worker has yet to poll it successfully for the first time."""
182
+
197
183
  LISTENING = "listening"
198
184
  """It takes inputs."""
199
185
 
186
+ FAILING = "failing"
187
+ """Its last polls failed, and the next one waits out a backoff."""
188
+
200
189
  BACKLOGGED = "backlogged"
201
190
  """As many runs from it are unsettled as ``max_in_flight`` allows; a new input is refused 503."""
202
191
 
@@ -211,11 +200,17 @@ class InputOutcome(StrEnum):
211
200
  """What came of one input that reached a source."""
212
201
 
213
202
  ACCEPTED = "accepted"
214
- """It became a run, and the caller was answered with where to read it."""
203
+ """It became a run, and the caller was answered with where to read it, or is held for its reply."""
204
+
205
+ REPLIED = "replied"
206
+ """It became a run whose answer the caller was held for: a reply, or the run's failure."""
215
207
 
216
208
  REFUSED = "refused"
217
209
  """It was refused before any run existed, and the reason is on the row."""
218
210
 
211
+ TIMED_OUT = "timed_out"
212
+ """It became a run the caller was held for, and no answer came before the caller's timeout."""
213
+
219
214
 
220
215
  class BodyKind(StrEnum):
221
216
  """How an inbound request's body was read."""
@@ -240,7 +235,7 @@ class DocumentKind(StrEnum):
240
235
 
241
236
  PIPELINE = "pipeline"
242
237
  TRIGGERS = "triggers"
243
- """Clocks and webhooks for a pipeline defined somewhere else."""
238
+ """Clocks for a pipeline defined somewhere else."""
244
239
 
245
240
 
246
241
  class ProvenanceSource(StrEnum):
@@ -1,7 +1,9 @@
1
1
  """A pipeline's sources: what each listens to, its state, what has arrived, and its token."""
2
2
 
3
+ from pydantic import SecretStr
4
+
3
5
  from dirigent_client.resources.base import Resource, query
4
- from dirigent_client.schemas import Page, SourceInputOut, SourceOut, SourceTokenOut
6
+ from dirigent_client.schemas import Page, SetSecretRequest, SourceInputOut, SourceOut, SourceTokenOut
5
7
 
6
8
 
7
9
  class Sources(Resource):
@@ -27,9 +29,19 @@ class Sources(Resource):
27
29
  return await self._one(SourceOut, "POST", f"/pipelines/{pipeline}/sources/{code}/$resume")
28
30
 
29
31
  async def rotate_token(self, pipeline: str, code: str) -> SourceTokenOut:
30
- """Mint a new token and forget the old one immediately; every caller has to be given it."""
32
+ """Mint a new token or signing secret and forget the old one immediately; every caller has to be given it."""
31
33
  return await self._one(SourceTokenOut, "POST", f"/pipelines/{pipeline}/sources/{code}/$rotate-token")
32
34
 
35
+ async def set_secret(self, pipeline: str, code: str, secret: str) -> SourceOut:
36
+ """Replace a signed source's signing secret with one its sender issued."""
37
+ body = SetSecretRequest(secret=SecretStr(secret))
38
+ return await self._one(
39
+ SourceOut,
40
+ "POST",
41
+ f"/pipelines/{pipeline}/sources/{code}/$set-secret",
42
+ json={"secret": body.secret.get_secret_value()},
43
+ )
44
+
33
45
  async def inputs(
34
46
  self, pipeline: str, code: str, *, after: str | None = None, limit: int | None = None
35
47
  ) -> Page[SourceInputOut]:
@@ -1,4 +1,4 @@
1
- """Triggers documents: the clocks and webhooks one document declares for another's pipeline."""
1
+ """Triggers documents: the clocks one document declares for another's pipeline."""
2
2
 
3
3
  from dirigent_client.resources.base import Resource, query
4
4
  from dirigent_client.schemas import Page, TriggerDocumentDetail, TriggerDocumentOut
@@ -16,5 +16,5 @@ class TriggerDocuments(Resource):
16
16
  return await self._one(TriggerDocumentDetail, "GET", f"/trigger-documents/{code}")
17
17
 
18
18
  async def delete(self, code: str) -> None:
19
- """Remove a triggers document and every schedule and webhook it owns."""
19
+ """Remove a triggers document and every schedule it owns."""
20
20
  await self._transport.request("DELETE", f"/trigger-documents/{code}")
@@ -68,6 +68,7 @@ from dirigent_client.schemas.sources import (
68
68
  EndpointInput,
69
69
  InputAccepted,
70
70
  RequestFacts,
71
+ SetSecretRequest,
71
72
  SourceChanges,
72
73
  SourceInputOut,
73
74
  SourceOut,
@@ -83,19 +84,13 @@ from dirigent_client.schemas.system import (
83
84
  WorkerOut,
84
85
  )
85
86
  from dirigent_client.schemas.triggers import (
86
- DeliveryOut,
87
87
  FiringOut,
88
- HookAccepted,
89
88
  ScheduleIn,
90
89
  ScheduleOut,
91
90
  SchedulePreview,
92
91
  SchedulePreviewRequest,
93
92
  TriggerDocumentDetail,
94
93
  TriggerDocumentOut,
95
- WatchOut,
96
- WebhookIn,
97
- WebhookOut,
98
- WebhookTokenOut,
99
94
  )
100
95
  from dirigent_common import JsonList, JsonMap
101
96
 
@@ -122,7 +117,6 @@ __all__ = [
122
117
  "ConnectionUpdate",
123
118
  "DagNode",
124
119
  "DagView",
125
- "DeliveryOut",
126
120
  "DiffSummary",
127
121
  "EndpointInput",
128
122
  "InputAccepted",
@@ -130,7 +124,6 @@ __all__ = [
130
124
  "ExampleOut",
131
125
  "FiringOut",
132
126
  "Health",
133
- "HookAccepted",
134
127
  "Identity",
135
128
  "IssuedTokenOut",
136
129
  "ItemOut",
@@ -159,6 +152,7 @@ __all__ = [
159
152
  "SourceChanges",
160
153
  "SourceInputOut",
161
154
  "SourceOut",
155
+ "SetSecretRequest",
162
156
  "SourceTokenOut",
163
157
  "Requirements",
164
158
  "RunAccepted",
@@ -190,9 +184,5 @@ __all__ = [
190
184
  "UserOut",
191
185
  "UserUpdate",
192
186
  "ValidationIssue",
193
- "WatchOut",
194
- "WebhookIn",
195
- "WebhookOut",
196
- "WebhookTokenOut",
197
187
  "WorkerOut",
198
188
  ]
@@ -76,12 +76,6 @@ class PipelineOut(WireModel):
76
76
  schedules: int = 0
77
77
  """How many clocks fire this pipeline."""
78
78
 
79
- webhooks: int = 0
80
- """How many inbound endpoints fire this pipeline."""
81
-
82
- watches: int = 0
83
- """How many watches keep a run of this pipeline waiting on a sensor."""
84
-
85
79
  last_run: LastRun | None = None
86
80
  """How the newest run of this pipeline went, or nothing when it has never run."""
87
81
 
@@ -116,7 +110,7 @@ class ApplyRequest(BaseModel):
116
110
  source_ref: str | None = Field(default=None, description="The file path or URL the document came from.")
117
111
  pause_schedules: bool = Field(
118
112
  default=False,
119
- description="Create the schedules and watches this apply brings into being already paused.",
113
+ description="Create the schedules this apply brings into being already paused.",
120
114
  )
121
115
 
122
116
 
@@ -336,27 +330,11 @@ class Materialized(WireModel):
336
330
  schedules_created: list[str] = Field(default_factory=list[str])
337
331
  schedules_updated: list[str] = Field(default_factory=list[str])
338
332
  schedules_removed: list[str] = Field(default_factory=list[str])
339
- webhooks_created: list[str] = Field(default_factory=list[str])
340
- webhooks_updated: list[str] = Field(default_factory=list[str])
341
- webhooks_removed: list[str] = Field(default_factory=list[str])
342
- watches_created: list[str] = Field(default_factory=list[str])
343
- watches_updated: list[str] = Field(default_factory=list[str])
344
- watches_removed: list[str] = Field(default_factory=list[str])
345
333
 
346
334
  @property
347
335
  def empty(self) -> bool:
348
336
  """Report whether the apply left every trigger exactly as it was."""
349
- return not (
350
- self.schedules_created
351
- or self.schedules_updated
352
- or self.schedules_removed
353
- or self.webhooks_created
354
- or self.webhooks_updated
355
- or self.webhooks_removed
356
- or self.watches_created
357
- or self.watches_updated
358
- or self.watches_removed
359
- )
337
+ return not (self.schedules_created or self.schedules_updated or self.schedules_removed)
360
338
 
361
339
 
362
340
  class PipelinePlan(WireModel):
@@ -395,7 +373,7 @@ class ApplyResult(WireModel):
395
373
  version: int | None = None
396
374
  dry_run: bool = False
397
375
  triggers: Materialized = Field(default_factory=Materialized)
398
- """Which schedules, webhooks and watches the document's ``triggers:`` section created, changed, or retired."""
376
+ """Which schedules the document's ``triggers:`` section created, changed, or retired."""
399
377
 
400
378
  sources: SourceChanges = Field(default_factory=SourceChanges)
401
379
  """Which source rows the apply created, changed, or retired, and the tokens it minted."""
@@ -44,7 +44,7 @@ class RunOut(WireModel):
44
44
  parent_run_id: UUID | None = None
45
45
  """The run whose step started this one, when a step of another run did."""
46
46
  triggered_by_id: UUID | None = None
47
- """What started the run: the source, schedule, webhook, watch, token or user, as its id."""
47
+ """What started the run: the source, schedule, token or user, as its id."""
48
48
 
49
49
  triggered_by_label: str | None = None
50
50
  source: str | None = None
@@ -3,7 +3,7 @@
3
3
  from datetime import datetime
4
4
  from uuid import UUID
5
5
 
6
- from pydantic import BaseModel, ConfigDict, Field, JsonValue
6
+ from pydantic import BaseModel, ConfigDict, Field, JsonValue, SecretStr
7
7
 
8
8
  from dirigent_client.enums import BodyKind, InputOutcome, SourceState
9
9
  from dirigent_client.schemas.common import WireModel
@@ -86,7 +86,10 @@ class SourceOut(WireModel):
86
86
  """How a caller of a received source authenticates: ``token`` or ``public``."""
87
87
 
88
88
  token_prefix: str | None = None
89
- """The leading characters of the token, so a caller's copy can be told apart from another."""
89
+ """The leading characters of the token or the signing secret, so a caller's copy can be told apart."""
90
+
91
+ signature_header: str | None = None
92
+ """For an ``hmac`` source, the header a caller's signature of the body arrives in."""
90
93
 
91
94
  in_flight: int = 0
92
95
  """How many runs it started are unsettled."""
@@ -101,21 +104,46 @@ class SourceOut(WireModel):
101
104
  """How many inputs were refused once their caller was let in."""
102
105
 
103
106
  last_input_at: datetime | None = None
107
+ summary: str | None = None
108
+ """What the source listens to, in one line its kind writes, such as the prefix it polls."""
109
+
110
+ polled_at: datetime | None = None
111
+ """When a poll of a polled source last succeeded."""
112
+
113
+ next_poll_at: datetime | None = None
114
+ failures: int = 0
115
+ """How many polls in a row have failed."""
116
+
117
+ last_error: str | None = None
104
118
  created_at: datetime
105
119
 
106
120
 
107
121
  class SourceTokenOut(WireModel):
108
- """A token freshly minted for a source, returned once and never readable again."""
122
+ """A credential freshly minted for a source, returned once and never readable again."""
109
123
 
110
124
  source_id: UUID
111
125
  pipeline: str
112
126
  code: str
127
+ auth: str = "token"
128
+ """``token`` for a bearer token a caller presents, ``hmac`` for a secret a caller signs the body with."""
129
+
130
+ header: str | None = None
131
+ """For ``hmac``, the header the signature arrives in."""
132
+
113
133
  token: str
134
+ """The token, or the signing secret."""
135
+
114
136
  prefix: str
115
137
  url_path: str
116
138
  """Where the source is called, so a caller can be configured without assembling the path by hand."""
117
139
 
118
140
 
141
+ class SetSecretRequest(WireModel):
142
+ """The signing secret a sender issued, to replace the one the instance minted."""
143
+
144
+ secret: SecretStr
145
+
146
+
119
147
  class SourceChanges(WireModel):
120
148
  """What applying a document did to the source rows its pipeline holds."""
121
149
 
@@ -137,8 +165,8 @@ class SourceInputOut(WireModel):
137
165
  id: int
138
166
  created_at: datetime
139
167
  outcome: InputOutcome
140
- status: int
141
- """The HTTP status the caller was answered with."""
168
+ status: int | None = None
169
+ """The HTTP status the caller was answered with, or null for an input a worker polled."""
142
170
 
143
171
  run_id: UUID | None = None
144
172
  code: str | None = None
@@ -146,8 +174,11 @@ class SourceInputOut(WireModel):
146
174
 
147
175
  reason: str | None = None
148
176
  params: JsonMap | None = None
149
- method: str
150
- path: str
177
+ method: str | None = None
178
+ path: str | None = None
179
+ label: str | None = None
180
+ """What a polled kind names the input, such as the object it found."""
181
+
151
182
  body_bytes: int = 0
152
183
  duration_ms: int = 0
153
184
  caller: str | None = None
@@ -1,9 +1,9 @@
1
- """A pipeline's persisted triggers: its schedules, its inbound webhooks, and its watches."""
1
+ """A pipeline's persisted triggers: its schedules."""
2
2
 
3
3
  from datetime import datetime
4
4
  from uuid import UUID
5
5
 
6
- from pydantic import BaseModel, Field, SecretStr, field_validator
6
+ from pydantic import BaseModel, Field, field_validator
7
7
 
8
8
  from dirigent_client.enums import (
9
9
  FiringOutcome,
@@ -11,7 +11,6 @@ from dirigent_client.enums import (
11
11
  ProvenanceSource,
12
12
  RunPriority,
13
13
  ScheduleKind,
14
- WebhookOutcome,
15
14
  )
16
15
  from dirigent_client.messages import (
17
16
  EMPTY_LOG_LEVEL_PATTERN,
@@ -112,84 +111,6 @@ class FiringOut(WireModel):
112
111
  detail: str | None = None
113
112
 
114
113
 
115
- class WebhookIn(BaseModel):
116
- """A webhook as a caller declares it; the token is never supplied, only minted."""
117
-
118
- code: EntityName
119
- name: str | None = None
120
- description: str | None = None
121
- params_from_payload: dict[str, str] = Field(default_factory=dict[str, str])
122
- hmac_secret: SecretStr | None = Field(default=None, min_length=1)
123
- """The signing secret, or null for an unsigned webhook; an empty string is neither."""
124
-
125
- rate_limit_per_minute: int = Field(default=60, ge=1)
126
- priority: RunPriority | None = Field(
127
- default=None,
128
- description="The priority every accepted delivery's run carries. Omitted takes the pipeline's own.",
129
- )
130
-
131
-
132
- class WebhookOut(WireModel):
133
- """A webhook as a listing shows it: everything about it except the token."""
134
-
135
- id: UUID
136
- code: str
137
- name: str | None = None
138
- description: str | None = None
139
- token_prefix: str
140
- params_from_payload: dict[str, str] = Field(default_factory=dict[str, str])
141
- signed: bool
142
- """Whether this webhook requires an HMAC signature; the secret itself never leaves."""
143
-
144
- active: bool
145
- managed: bool
146
- trigger_document: str | None = None
147
- """The triggers document that declares this row, or null when the pipeline's own does."""
148
-
149
- rate_limit_per_minute: int
150
- priority: RunPriority | None = None
151
- """The priority every accepted delivery's run carries, or null when it takes the pipeline's own."""
152
-
153
- last_delivery_at: datetime | None = None
154
- created_at: datetime
155
-
156
-
157
- class WatchOut(WireModel):
158
- """A watch as a listing shows it: what it waits on, and how its last run of waiting went."""
159
-
160
- id: UUID
161
- code: str
162
- name: str | None = None
163
- description: str | None = None
164
- step: str
165
- """The root sensor step every run it arms waits on."""
166
-
167
- params: JsonMap = Field(default_factory=dict)
168
- paused: bool
169
- managed: bool
170
- trigger_document: str | None = None
171
- """The triggers document that declares this row, or null when the pipeline's own does."""
172
-
173
- cursor: JsonMap | None = None
174
- """Where the last successful poke of the watched step left off, which the next run starts from."""
175
-
176
- waiting_run_id: UUID | None = None
177
- """The run waiting on the sensor now, or null between one run and the next."""
178
-
179
- failures: int = 0
180
- """How many waits in a row have ended without the sensor succeeding."""
181
-
182
- last_error: str | None = None
183
- """Why the last wait ended without the sensor succeeding, or null once one has succeeded since."""
184
-
185
- last_error_at: datetime | None = None
186
- rearm_at: datetime | None = None
187
- """When a watch backing off after a failure arms its next run."""
188
-
189
- last_armed_at: datetime | None = None
190
- created_at: datetime
191
-
192
-
193
114
  class TriggerDocumentOut(WireModel):
194
115
  """A ``kind: triggers`` document as a listing shows it."""
195
116
 
@@ -213,36 +134,3 @@ class TriggerDocumentDetail(TriggerDocumentOut):
213
134
 
214
135
  document: JsonMap
215
136
  schedules: list[str] = Field(default_factory=list[str])
216
- webhooks: list[str] = Field(default_factory=list[str])
217
- watches: list[str] = Field(default_factory=list[str])
218
-
219
-
220
- class WebhookTokenOut(WireModel):
221
- """A freshly minted webhook token, returned once and never readable again."""
222
-
223
- webhook_id: UUID
224
- code: str
225
- token: str
226
- prefix: str
227
- url_path: str
228
- """Where to POST, so a caller can be configured without assembling the path by hand."""
229
-
230
-
231
- class HookAccepted(WireModel):
232
- """What an accepted delivery answers with: the run it started, or why it started none."""
233
-
234
- run_id: UUID | None = None
235
- outcome: WebhookOutcome
236
- detail: str | None = None
237
-
238
-
239
- class DeliveryOut(WireModel):
240
- """One inbound delivery, and what came of it."""
241
-
242
- id: int
243
- created_at: datetime
244
- outcome: WebhookOutcome
245
- run_id: UUID | None = None
246
- reason: str | None = None
247
- mapped_params: JsonMap | None = None
248
- source: str | None = None
@@ -1,29 +0,0 @@
1
- """A pipeline's watches: the sensor each keeps a run waiting on, and how that is going."""
2
-
3
- from dirigent_client.resources.base import Resource, query
4
- from dirigent_client.schemas import Page, WatchOut
5
-
6
-
7
- class Watches(Resource):
8
- """Read, pause, and resume the watches hanging from a pipeline."""
9
-
10
- async def list(self, pipeline: str, *, after: str | None = None, limit: int | None = None) -> Page[WatchOut]:
11
- """List every watch on a pipeline, with the run each one has waiting."""
12
- return await self._many(
13
- WatchOut,
14
- "GET",
15
- f"/pipelines/{pipeline}/triggers/watches",
16
- params=query(after=after, limit=limit),
17
- )
18
-
19
- async def get(self, pipeline: str, code: str) -> WatchOut:
20
- """Read one watch by code."""
21
- return await self._one(WatchOut, "GET", f"/pipelines/{pipeline}/triggers/watches/{code}")
22
-
23
- async def pause(self, pipeline: str, code: str) -> WatchOut:
24
- """Stop a watch, cancelling the run it has waiting, and keep where it left off."""
25
- return await self._one(WatchOut, "POST", f"/pipelines/{pipeline}/triggers/watches/{code}/$pause")
26
-
27
- async def resume(self, pipeline: str, code: str) -> WatchOut:
28
- """Start a watch again, arming a run from where its last success left off."""
29
- return await self._one(WatchOut, "POST", f"/pipelines/{pipeline}/triggers/watches/{code}/$resume")
@@ -1,80 +0,0 @@
1
- """A pipeline's inbound webhooks: their mapping, their token, and what has arrived."""
2
-
3
- from pydantic import SecretStr
4
-
5
- from dirigent_client.enums import RunPriority
6
- from dirigent_client.resources.base import Resource, query, request_body
7
- from dirigent_client.schemas import DeliveryOut, Page, WebhookIn, WebhookOut, WebhookTokenOut
8
-
9
-
10
- class Webhooks(Resource):
11
- """Declare, enable, rotate, and read the webhooks hanging from a pipeline."""
12
-
13
- async def list(self, pipeline: str, *, after: str | None = None, limit: int | None = None) -> Page[WebhookOut]:
14
- """List every webhook on a pipeline, with its mapping but never its token."""
15
- return await self._many(
16
- WebhookOut,
17
- "GET",
18
- f"/pipelines/{pipeline}/triggers/webhooks",
19
- params=query(after=after, limit=limit),
20
- )
21
-
22
- async def get(self, pipeline: str, code: str) -> WebhookOut:
23
- """Read one webhook by code, with its mapping but never its token."""
24
- return await self._one(WebhookOut, "GET", f"/pipelines/{pipeline}/triggers/webhooks/{code}")
25
-
26
- async def create(
27
- self,
28
- pipeline: str,
29
- code: str,
30
- *,
31
- name: str | None = None,
32
- description: str | None = None,
33
- params_from_payload: dict[str, str] | None = None,
34
- hmac_secret: str | None = None,
35
- rate_limit_per_minute: int = 60,
36
- priority: RunPriority | None = None,
37
- ) -> WebhookTokenOut:
38
- """Declare a webhook and return its token, which is shown here and nowhere else again."""
39
- payload = WebhookIn(
40
- code=code,
41
- name=name,
42
- description=description,
43
- params_from_payload=params_from_payload or {},
44
- hmac_secret=SecretStr(hmac_secret) if hmac_secret else None,
45
- rate_limit_per_minute=rate_limit_per_minute,
46
- priority=priority,
47
- )
48
- return await self._one(
49
- WebhookTokenOut,
50
- "POST",
51
- f"/pipelines/{pipeline}/triggers/webhooks",
52
- json=request_body(payload),
53
- )
54
-
55
- async def rotate_token(self, pipeline: str, code: str) -> WebhookTokenOut:
56
- """Mint a new token and forget the old one immediately; callers must be updated."""
57
- return await self._one(WebhookTokenOut, "POST", f"/pipelines/{pipeline}/triggers/webhooks/{code}/$rotate-token")
58
-
59
- async def enable(self, pipeline: str, code: str) -> WebhookOut:
60
- """Accept deliveries again on the token that was already issued."""
61
- return await self._one(WebhookOut, "POST", f"/pipelines/{pipeline}/triggers/webhooks/{code}/$enable")
62
-
63
- async def disable(self, pipeline: str, code: str) -> WebhookOut:
64
- """Refuse deliveries without rotating or losing the token."""
65
- return await self._one(WebhookOut, "POST", f"/pipelines/{pipeline}/triggers/webhooks/{code}/$disable")
66
-
67
- async def delete(self, pipeline: str, code: str) -> None:
68
- """Remove a webhook, its token, and its delivery history."""
69
- await self._transport.request("DELETE", f"/pipelines/{pipeline}/triggers/webhooks/{code}")
70
-
71
- async def deliveries(
72
- self, pipeline: str, code: str, *, after: str | None = None, limit: int | None = None
73
- ) -> Page[DeliveryOut]:
74
- """Read what has arrived, newest first, refusals included."""
75
- return await self._many(
76
- DeliveryOut,
77
- "GET",
78
- f"/pipelines/{pipeline}/triggers/webhooks/{code}/deliveries",
79
- params=query(after=after, limit=limit),
80
- )