Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/backend/app/extraction/support_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ def _code_list(items: tuple[str, ...]) -> str:
"authentication-isolation",
"Authentication and owner isolation",
PublicStatus.IMPLEMENTED,
"Email/password, Argon2, short-lived access tokens, rotating refresh tokens with reuse detection. Google and GitHub OAuth sign-in and account linking are implemented but inert until provider credentials are configured, and never create an account. Registration is gated by an admin-managed email allowlist in every environment except `development` (the default when running from source), where any address may register, and except the first account on an empty instance, which becomes its owner. Registration does not verify email ownership, so an approved address can be claimed by whoever registers it first; there is no admin role or in-app approval. Protected resources are owner-scoped; non-owner access returns 404.",
"Email/password, Argon2, short-lived access tokens, rotating refresh tokens with reuse detection. Google and GitHub OAuth sign-in and account linking are implemented but inert until provider credentials are configured, and can create an account for a verified new identity only through the same email-approval/bootstrap gate as password registration. Registration is gated by an admin-managed email allowlist in every environment except `development` (the default when running from source), where any address may register, and except the first account on an empty instance, which is permitted without prior approval and receives no administrator role. Registration does not verify email ownership, so an approved address can be claimed by whoever registers it first; there is no admin role or in-app approval. Protected resources are owner-scoped; non-owner access returns 404.",
("product.authentication-isolation",),
),
PublicCapability(
Expand Down
21 changes: 21 additions & 0 deletions apps/backend/tests/test_oauth_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,24 @@ def test_lists_only_the_requested_users_identities(self, db):
service = _make_service(db, {})
assert [i.provider for i in service.linked_identities(user_a.id)] == ["google"]
assert [i.provider for i in service.linked_identities(user_b.id)] == ["github"]


@pytest.mark.parametrize("approved", [False, True])
def test_public_oauth_capability_matches_verified_identity_creation_gate(db, approved):
import asyncio
from app.extraction.support_matrix import PUBLIC_CAPABILITIES

capability = next(item for item in PUBLIC_CAPABILITIES if item.id == "authentication-isolation")
assert "can create an account for a verified new identity" in capability.statement
assert "same email-approval/bootstrap gate" in capability.statement
_create_user(db, "existing-contract@example.com")
email = "capability-newcomer@example.com"
if approved:
approve_email(db, email)
identity = OAuthIdentityInfo(subject="contract-identity", email=email, email_verified=True, display_name="Contract")
service = _make_service(db, {"google": FakeProviderClient(identity=identity)})
url = service.start("google", intent="login", frontend_redirect_base="http://localhost:5173")
state = url.split("state=")[1].split("&")[0]
_, result = asyncio.run(service.complete_callback("google", state=state, code="c", provider_error=None))
assert (result.kind == "session") is approved
assert db.query(User).filter(User.email == email).count() == int(approved)
2 changes: 1 addition & 1 deletion docs/CAPABILITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ release; `dev` carries active development.
| --- | --- | --- |
| Archive upload and public GitHub import | **Implemented** | ZIP/TAR-family archives and shallow public GitHub HTTPS clones; size and path-safety limits apply. Private GitHub cloning and other repository hosts are not supported. |
| Repository explorer | **Implemented** | Owner-scoped file tree plus bounded text/image preview, binary detection, and truncation. |
| Authentication and owner isolation | **Implemented** | Email/password, Argon2, short-lived access tokens, rotating refresh tokens with reuse detection. Google and GitHub OAuth sign-in and account linking are implemented but inert until provider credentials are configured, and never create an account. Registration is gated by an admin-managed email allowlist in every environment except `development` (the default when running from source), where any address may register, and except the first account on an empty instance, which becomes its owner. Registration does not verify email ownership, so an approved address can be claimed by whoever registers it first; there is no admin role or in-app approval. Protected resources are owner-scoped; non-owner access returns 404. |
| Authentication and owner isolation | **Implemented** | Email/password, Argon2, short-lived access tokens, rotating refresh tokens with reuse detection. Google and GitHub OAuth sign-in and account linking are implemented but inert until provider credentials are configured, and can create an account for a verified new identity only through the same email-approval/bootstrap gate as password registration. Registration is gated by an admin-managed email allowlist in every environment except `development` (the default when running from source), where any address may register, and except the first account on an empty instance, which is permitted without prior approval and receives no administrator role. Registration does not verify email ownership, so an approved address can be claimed by whoever registers it first; there is no admin role or in-app approval. Protected resources are owner-scoped; non-owner access returns 404. |
| Analysis lifecycle | **Implemented** | Database-backed, cancellable job with progress, bounded retry, lease renewal, and stale-worker recovery. |
| Repository Intelligence | **Implemented with disclosed limits** | Immutable, revision-addressed `ri.v1` snapshots with normalized facts, evidence, query APIs, and a total canonical graph hash. Semantic extraction is strongest for supported Python and TypeScript/JavaScript constructs. |
| Repository lineage | **Implemented with disclosed limits** | Repeated imports of the same repository and branch are grouped into a durable, owner-scoped lineage with duplicate-revision detection (RFC-0002). `GET /repositories/{id}/lineage` returns the ordered history and the repository detail page renders it. Refresh and cross-revision comparison on top of a lineage are not built. |
Expand Down
Loading