Release 0.4.0: auto-set RFC owner = proposer
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -496,6 +496,11 @@ def test_propose_to_super_draft_vertical(app_with_fake_gitea):
|
||||
proposal = r.json()
|
||||
assert proposal["entry"]["title"] == "Open Human Model"
|
||||
assert proposal["entry"]["state"] == "super-draft"
|
||||
# §9.2: the proposer is the implicit first owner at propose time.
|
||||
# The owners field is a single-element list containing exactly the
|
||||
# session user's gitea_login — no request-supplied owner field
|
||||
# exists or is honored.
|
||||
assert proposal["entry"]["owners"] == ["alice"]
|
||||
assert proposal["affordances"]["merge"] is True
|
||||
|
||||
# Owner merges. The catalog picks up the new super-draft.
|
||||
@@ -516,6 +521,10 @@ def test_propose_to_super_draft_vertical(app_with_fake_gitea):
|
||||
view = r.json()
|
||||
assert view["state"] == "super-draft"
|
||||
assert "shared definition" in view["body"]
|
||||
# §9.2: the auto-set proposer-owner survives the meta-repo round-trip
|
||||
# — it's in the file's frontmatter on main after merge, not just
|
||||
# in the pending-PR view above.
|
||||
assert view["owners"] == ["alice"]
|
||||
|
||||
# The pending-ideas list no longer carries the merged proposal.
|
||||
r = client.get("/api/proposals")
|
||||
@@ -568,6 +577,37 @@ def test_anonymous_cannot_propose(app_with_fake_gitea):
|
||||
assert r.status_code == 401
|
||||
|
||||
|
||||
def test_proposer_is_auto_owner_request_payload_ignored(app_with_fake_gitea):
|
||||
"""§9.2: the owners field on the new entry is always exactly
|
||||
`[session.gitea_login]`. The propose endpoint never accepts an owner
|
||||
from the client; a request payload that smuggles one in is ignored
|
||||
by the Pydantic body model and the auto-set value lands instead.
|
||||
"""
|
||||
from fastapi.testclient import TestClient
|
||||
app, _fake = app_with_fake_gitea
|
||||
with TestClient(app) as client:
|
||||
provision_user_row(user_id=11, login="alice", role="contributor")
|
||||
sign_in_as(client, user_id=11, gitea_login="alice", display_name="Alice", role="contributor")
|
||||
# Extra unknown fields like `owners` are dropped by the
|
||||
# ProposeBody model; the session user is the only source of truth.
|
||||
r = client.post("/api/rfcs/propose", json={
|
||||
"title": "Spoof attempt",
|
||||
"slug": "spoof-attempt",
|
||||
"pitch": "p",
|
||||
"tags": [],
|
||||
"owners": ["mallory", "eve"],
|
||||
"proposed_by": "mallory@test",
|
||||
})
|
||||
assert r.status_code == 200, r.text
|
||||
pr_number = r.json()["pr_number"]
|
||||
r = client.get(f"/api/proposals/{pr_number}")
|
||||
assert r.status_code == 200, r.text
|
||||
entry = r.json()["entry"]
|
||||
assert entry["owners"] == ["alice"]
|
||||
# proposed_by also comes from the session, never the body.
|
||||
assert entry["proposed_by"] in ("alice@test", "alice")
|
||||
|
||||
|
||||
def test_withdraw_by_proposer_works(app_with_fake_gitea):
|
||||
from fastapi.testclient import TestClient
|
||||
app, _fake = app_with_fake_gitea
|
||||
|
||||
Reference in New Issue
Block a user