Add Tangled rule-submission backend - #405
Closed
julietshen wants to merge 3 commits into
Closed
Conversation
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
New ui-api blueprint for authoring SML rule drafts from the UI, with submission routed through a pluggable backend so each deployment picks where drafts go for review. Endpoints (all gated by a new CAN_EDIT_RULE_DRAFTS ability, granted to super_user): get-source, validate, vocabulary, submit, pending, and parse-into-builder. Validate and submit splice the draft into the engine's loaded sources and re-run the same AST validation the engine uses; submit re-validates server-side before touching any backend. Backends implement the RuleSubmissionBackend Protocol and are selected by OSPREY_RULES_SUBMISSION_BACKEND: - null (default): fails fast with 503 so an unconfigured install never writes anything - github: opens a PR via the REST API; supports GitHub Enterprise - local: writes into a mounted rules directory Contract and safety details: - SubmissionResult/PendingDraft.to_json spread extras first so a backend-specific extra can't shadow the canonical title/url/ main_sml_updated fields the UI depends on - Forge transport failures (connection refused, timeout) become the structured 502 the UI renders, not an unhandled 500, via a shared _rule_drafts_git_common.request() helper that also holds the branch-name and main.sml Require helpers - main.sml is rejected as a draft path: wholesale-replacing the engine entry point is not a draft; wiring a rule in is the controlled wire_into_main append Adopter docs for the env vars are in docs/user/manage.md. Follow-ups add the rule-editor UI, a GitLab backend, and a Tangled (ATProto) backend. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZ4RQtuHCCgurfpjfPXXAM
GitLabBackend opens a merge request via the REST v4 API, mirroring the GitHub adapter: create branch, commit the draft (plus an optional main.sml Require line), open the MR. Works with gitlab.com and self-hosted instances via OSPREY_GITLAB_URL. Configured with OSPREY_RULES_SUBMISSION_BACKEND=gitlab, OSPREY_GITLAB_PROJECT, and OSPREY_GITLAB_TOKEN. Shares the branch-name / main.sml Require helpers and the transport-error wrapper with the GitHub backend via _rule_drafts_git_common, so a GitLab outage returns the structured 502 the UI renders rather than a 500. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZ4RQtuHCCgurfpjfPXXAM
TangledBackend targets Tangled, an ATProto-native git host where pulls are records rather than REST resources: it authenticates the configured Bluesky identity, then writes an sh.tangled.repo.pull record (carrying a gzipped git format-patch blob) to the user's PDS via com.atproto.repo.createRecord. The hand-built patch has a single sanitization choke point: free-text summary lines that git-am would read as patch structure (---, diff -, Index:, mbox From boundaries) are quoted, and newlines/angle brackets are stripped from the From:/Subject: headers, so a crafted summary can't smuggle hunks for arbitrary files into the patch a maintainer applies. Shares the branch-name helper and the transport-error wrapper with the other backends via _rule_drafts_git_common. Current limits, both returning 501: new rules only (edits would need a diff against the existing file) and no wire_into_main (multi-file patch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZ4RQtuHCCgurfpjfPXXAM
julietshen
force-pushed
the
julietshen/rule-drafts-tangled
branch
from
July 3, 2026 18:25
9c0d4c2 to
ea15ebe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #402 and the GitLab backend PR. Review those first; this PR's diff will show their commits until they merge.
Adds
TangledBackendtargeting Tangled, an ATProto-native git host where pulls are records rather than REST resources. The adapter authenticates the configured Bluesky identity, then writes ansh.tangled.repo.pullrecord (carrying a gzippedgit format-patchblob) to the user's PDS viacom.atproto.repo.createRecord.Current limits, both returning 501 with an explanatory message: new rules only (edits would require rendering a diff against the existing file) and no
wire_into_main(would require a multi-file patch).The hand-built patch has a single sanitization choke point: free-text summary lines that git-am would read as patch structure (
---,diff -,Index:,Frommbox boundaries) are quoted, and newlines/angle brackets are stripped from theFrom:/Subject:headers, so a crafted summary can't smuggle hunks for arbitrary files into the patch a maintainer applies. Covered by tests, and verified end-to-end with realgit am.Configuration:
OSPREY_RULES_SUBMISSION_BACKEND=tangledplusOSPREY_TANGLED_HANDLE,OSPREY_TANGLED_APP_PASSWORD,OSPREY_TANGLED_REPO,OSPREY_TANGLED_REPO_DID(docs indocs/user/manage.md).Checklist
uv run ruff check .passesCHANGELOG.md