Commit graph

16 commits

Author SHA1 Message Date
Sipke Schoorstra 3921715060
docs: authorization model design (spec 013) (#7978)
* docs: add authorization model design (spec 013)

Replaces Elsa's ad-hoc permission vocabulary with a structured two-axis
model. Design only -- no code changes.

A census of all 150 permission-declaring endpoints found the current
vocabulary has no model behind it: "read:*" is a literal claim value
rather than a pattern, so it authorizes 12 of roughly 40 read endpoints;
57 permission strings appear as inline literals across 174 call sites in
three competing naming schemes; omitting a declaration fails open; and
four parallel enforcement mechanisms leave no single place to audit.

A permission becomes {resource}:{verb}, with both axes open and
string-keyed and contributed by modules through descriptors. A trailing
wildcard matches the named node and all descendants, so workflows/*:view
is a single grant covering definitions, instances, executions and every
descriptor endpoint, including ones registered in later releases.
Wildcards are the only construct with forward reach; there are no
aggregates and no verb implies another. Coherence without closure comes
from a recommended core verb set as convention, per Principle III.

A closed verb enumeration was drafted and rejected: fitting the census to
seven verbs forced six mappings, invented three sub-resources, and every
open question it produced was an artefact of the closure.

Contents:
- spec.md: 41 functional requirements, 9 user stories, 7 success criteria
- plan.md: 5 milestones, constitution check, project structure
- research.md: grounded assessment and decision record D1-D23
- contracts/permissions.md: resource tree plus the full migration mapping,
  verified complete against all 57 literal permissions in the codebase
- contracts/rest-api.md: catalog, reach report, and introspection
- tasks.md: 63 tasks across 5 phases, tagged by user story

Breaking changes are documented in the spec and tracked in the issue:
legacy permission strings stop authorizing; the migration expands rather
than renames, because several sub-resources are granularity increases;
read:* and exec:* become materially more powerful; and the C#/Python
expression permissions are removed rather than translated, which is a
deliberate reduction in control.

Refs #7974, #7972, #7975

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: scope the evaluator consolidation to permission checks

FR-016 and FR-017 swept in the mid-handler AuthorizeAsync calls, which in
the workflow API are the NotReadOnlyPolicy checks. Those enforce
deployment read-only mode -- whether the instance accepts mutations at
all -- which is orthogonal to whether a principal holds a permission. A
workflow author with full grants is still refused while the deployment is
read-only, and correctly so. Folding them into the permission evaluator
would conflate two independent axes and make read-only mode expressible
as a grant, which it must not be.

The consolidation still covers four parallel mechanisms, but not the same
four: FastEndpoints permissions, named ASP.NET policies (3 sites),
hand-rolled claim inspections (15 files), and SignalR hub checks (4 hubs).

- FR-016 scoped to permission decisions, with the separate axis named
- FR-017 states the NotReadOnlyPolicy exclusion and why
- FR-018 said "scope value"; corrected to "verb" after D13 opened the
  verb axis
- SC-003, the plan's constitution row, scale figures and milestone 3
  updated to match
- D5 and D6 marked where they still reference the withdrawn mask
- D24 records the correction rather than rewriting the assessment
- Permission string count corrected from 56 to the verified 57

Refs #7974

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: apply module-owner review outcomes to the authorization model

Resolves the five open vocabulary questions and the two model gaps they
surfaced.

- External Authentication descriptors get their own resource,
  external-authentication/descriptors:view, as a single node. One legacy
  permission governs all six endpoints, which is the same principle that
  gives workflows/descriptors nine separate resources -- those were
  separately permissioned already. The tree reflects the API in both cases.
- /user-options stays on identity-links:view. It is a user search backing
  the link picker and the linking UI cannot function without it. Recorded
  consequence: identity-link rights confer tenant-wide user enumeration in
  a reduced projection, without identity/users:view.
- The roles:assign descriptor is corrected to describe what it guards.
  Setting defaultRoleIds is guarded by the ordinary subset rule, so no
  escalation was possible either way.
- The two Broker/Logout.cs endpoints declare differently: Logout is
  authenticated-only because it reads the session claim from the
  principal, ContinueLogout is anonymous because the route handle carries
  the authority. ContinueLogout inheriting the authenticated default today
  is a probable live bug -- the identity provider redirects the browser
  there during upstream logout, possibly after the Elsa session is gone.
  The fail-closed gate surfaced it; this work did not introduce it.
- T028 splits four ways along resource-group seams (31/20/15/12 files)
  rather than landing as one 78-file pull request.

Two model gaps followed, one closed and one recorded:

- FR-019 now accepts a third declaration state, authenticated-only.
  Logout needs an identity but no grant, which the two-state rule could
  not express without either a fabricated permission or a gate exemption,
  and an exemption list is a hole in a fail-closed guarantee.
- Conjunctive requirements remain unexpressible. An endpoint declares one
  resource and one verb, so "needs link rights and user read" cannot be
  stated declaratively. Recorded so the next case is not solved ad hoc.

Refs #7974

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: link the authorization review follow-ups

Refs #7976, #7977

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: mark T062 complete

The five module-owner questions are resolved and folded into the
vocabulary, so Phase 2 is unblocked.

Refs #7974

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: address review findings on the authorization model

Automated review on #7978 surfaced several genuine gaps. Two changed the
model rather than the prose.

A bare `*` now parses as `*:*`. FR-021 forbids a superuser sentinel while
D2 requires a stored `*` to keep authorizing so no instance locks itself
out, and the seed default is ["*"]. These are reconciled at the parse
layer rather than the evaluation layer: a string with no colon consisting
solely of `*` normalizes to resource `*`, verb `*`. The evaluator never
sees a sentinel, so FR-021 holds.

Wildcards are validated structurally, not against the catalog.
`workflows/*` matches no single descriptor and `*` is deliberately absent
from supported verbs, so naive descriptor validation would have rejected
the grants US1 is built on. Concrete resources and verbs validate against
the registry; wildcard segments are accepted when syntactically well
formed, including when they match nothing today, since installing a
module later is what gives such a grant meaning. Adds FR-012a and
T022a/T022b, which also close a real gap: the role write paths persist
request.Permissions after only the caller-subset check, and no task had
wired registry validation into them.

Also:
- Counts corrected to 47 resources and 23 verbs; the PR said 45/21 and
  the tracking issue 44/21, having drifted as resources were added
- Post-design constitution re-check performed and recorded, with the 17
  module-specific verbs called out as a Principle VII note
- T025 scoped to descriptor consistency; it asserted endpoint resolution
  during Phase 2, when endpoints still declare legacy strings
- T047a carries the security stamp's provider migrations, so Phase 4 no
  longer depends on Phase 5 to be shippable
- T038a covers wildcard containment in RoleAuthorizationService
- Staleness guidance corrected: the catalog and reach report are registry
  snapshots, not token projections
- Abbreviated migration rows (`:write`, `:delete`, `:update`) spelled out
  so the table is mechanically checkable
- rest-api.md now lists all three endpoints and their differing access
- American English throughout, per the constitution

Refs #7974

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: publish the migration guide alongside the contract

The vocabulary contract named docs/migrations/authorization-model.md as
the authoritative source for converting stored permissions, but the file
lived only on the implementation branch. A design change that
intentionally stops legacy grants authorizing must not point operators at
an upgrade guide it does not ship: following a dangling reference is how
roles get silently narrowed, or non-admin roles locked out, during an
upgrade.

Publishes the guide and ADR 0012 here, and marks T057-T061 complete. The
contract's reference is now a working relative link.

Refs #7974

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:19:22 +02:00
Sipke Schoorstra 5429008d98
Add architecture and practices documentation
Introduce comprehensive documentation covering architecture (ARCHITECTURE.md), concerns (CONCERNS.md), coding conventions (CONVENTIONS.md), integrations (INTEGRATIONS.md), technology stack (STACK.md), codebase structure (STRUCTURE.md), and testing patterns (TESTING.md). Enhance testing with additional test cases for external sign-in flows, ensuring accurate timestamp recording for identity links.
2026-08-03 23:46:38 +02:00
Sipke Schoorstra 103028452f
feat: introduce HTTP webhooks module
Adds a new `Elsa.Http.Webhooks` module, enabling workflows to receive incoming webhook events and dispatch outgoing webhooks. This integrates the WebhooksCore library.

Further improvements include:
- Enhanced validation for configured application instance names, providing clearer feedback, especially regarding Azure Service Bus entity name limits.
- Improved API error reporting for shell reload operations, distinguishing between blueprint not found (404) and other failures (503).
- Updated release announcement rendering to dynamically reference the correct major.minor release line for feedback messages.
2026-08-03 02:08:15 +02:00
Sipke Schoorstra fe125ac336
Fix external authentication review findings 2026-08-02 03:35:39 +02:00
Sipke Schoorstra 6e3ed5c4e0
Remove migration for external authentication in EFCore.Sqlite module 2026-07-31 14:31:18 +02:00
Sipke Schoorstra 95b2ce8d84
Revise external authentication architecture 2026-07-25 02:35:56 +02:00
Sipke Schoorstra ef83541edd
Add external authentication broker 2026-07-24 19:04:26 +02:00
Sipke Schoorstra 974cbe740a
Skills 2026-06-25 15:19:31 +02:00
Sipke Schoorstra 4266421a4c
Refactor Fault Propagation and Simplify Bookmark Management (#6545)
* Refactor bookmark management and add new features

Streamlined bookmark handling by eliminating temporary storage in `ActivityExecutionContext` and directly managing bookmarks in `WorkflowExecutionContext`. Documented architectural decisions using ADRs.

* Regenerate EF Core migrations

* Refactor fault tracking to use AggregatedFaultCount property.

Replaces FaultCount with AggregatedFaultCount across the codebase to improve clarity and consistency in fault tracking. Updates related methods, properties, and data mappings to align with the new terminology. Fixes initialization issue with nullable inputs in Fault class.

* Add migration to track fault counts in runtime (V3.5)

This migration adds a new column, "AggregatedFaultCount," to the "ActivityExecutionRecords" table. The column is an integer, non-nullable, with a default value of 0, and enables tracking aggregated fault occurrences. The migration also includes a rollback to remove this column if needed.

* Fix typo in ADR 0004 regarding bookmark management convention

Corrected a spelling mistake in the ADR documentation by changing "determins" to "determines." This ensures clarity and maintains the professionalism of the document. No functional changes were made.

* Refine fault propagation logic for child-parent activities

Replace automatic fault transitions of parent activities with an aggregate fault count for descendant activities. This avoids premature state changes while still indicating child activity faults, improving workflow resilience and accuracy.

* Remove signal-driven fault propagation ADR and renumber bookmarks ADR

The ADR for signal-driven fault propagation was deleted, and the direct bookmark management ADR was renamed and renumbered accordingly. Related references in the table of contents, graph, and solution file were updated to reflect these changes.

* Refactor DeleteBookmarks to improve readability.

Reformatted the BookmarkFilter initialization for better clarity and maintainability. This change ensures the code is more aligned with modern C# conventions and improves overall readability. No behavior or functionality has been altered.

* Refactor naming for "AggregatedFaultCount" to "AggregateFaultCount"

Standardized the terminology across the codebase and migrations by renaming all references of "AggregatedFaultCount" to "AggregateFaultCount" for improved consistency and readability. Updated relevant logic, models, migrations, and database contexts accordingly.
2025-04-10 15:01:49 +02:00
Sipke Schoorstra 3984870745
Create bounty-announcement-template.md 2024-07-04 10:27:32 +02:00
Sipke Schoorstra 561247a406
Create bounty-quality-standards.md 2024-07-04 10:25:38 +02:00
Sipke Schoorstra b589147258 Added more escaping 2024-04-10 21:08:59 +02:00
Sipke Schoorstra 4685dca1e9 Update markdown formatting in bounty-footer.md 2024-04-10 21:07:47 +02:00
Sipke Schoorstra b9fb80a949 Add new requirement in bounty-footer.md
The commit adds a new task in the check list of the bounty-footer file. The new requirement compels the user to describe their proposed solution either in a comment on the issue or in a discussion linked to the bounty, before beginning their work.
2024-04-10 20:22:18 +02:00
Sipke Schoorstra 97d1280c15 Update bounty footer content in docs
The footer content in the bounty documentation has been expanded to provide clearer instructions for potential contributors. It includes instructions on how to announce an intention to claim a bounty and what to do before starting. An example template for bounty candidacy has also been added for the ease of contributors.
2024-04-10 20:18:06 +02:00
Sipke Schoorstra b421b00e16 Add Bounty Label Workflow and Documentation
A new GitHub Actions workflow has been introduced for appending a footer to issues that have been tagged with a 'bounty' label. The text for this footer is taken from a newly added "bounty-footer.md" file in the "docs" folder. The workflow is triggered whenever an issue is labeled, and it checks out the repository, reads the footer content, and appends it to the labeled issue. The "bounty-footer.md" and the workflow itself are also added to the solution file.
2024-04-10 19:18:59 +02:00