Merge branch 'worktree-check-security-audit'
Security and frontend-correctness hardening: analytics IDOR fix, scraper log scrubbing, lowercase email normalisation (migration 009), stale-response guards in the plan hooks, busy flags cleared unconditionally across all useLatestRequest consumers, Calendar no longer blanks on mutation, plus dependabot/CI config and removal of the stray frontend/out.js. Conflicts came from main's later "day assertions" restructure, which made usePlannedDays read-only and replaced the calendar's per-day add/update with useDayAssertions.assertDay. Both intents kept: - usePlannedDays: branch's fetch machinery (isRefreshing, in-flight dedup, unguarded busy clear); mutators dropped as on main. - usePlanSync: branch's useLatestRequest guard also applied to main's new syncWithWish. - useDayAssertions / useLatestBalance (new on main): busy flag now cleared unconditionally, as the branch did for every other consumer. - useDayAssertions.assertDay gains the branch's `skipRefresh` option and a `refresh`, so Calendar's multi-day save keeps the batch shape (N writes, one trailing bumpPlanVersion + one assertions refresh) on main's assertDay path. Branch's M7 tests ported from the removed add/update API to assertDay. - PlanSyncProvider: branch's isAuthenticated gate kept; eviction-preview state stays removed as on main. - usePlannedDayExclusions.ts stays deleted (superseded by useDayAssertions). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4wjgbVL4HAC5Rdaw75VbV
This commit is contained in:
@@ -44,7 +44,9 @@ async def get_overview(
|
||||
pd_repo: PersonalDataRepositoryDep,
|
||||
workspace_repo: WorkspaceRepositoryDep,
|
||||
vacation_repo: VacationDaysRepositoryDep,
|
||||
scope: WorkspaceScopeDep,
|
||||
) -> WorkspaceOverviewResponse:
|
||||
await scope.check_child(child_id)
|
||||
service = _make_service(
|
||||
leave_repo, planned_repo, child_repo, pd_repo, workspace_repo, vacation_repo
|
||||
)
|
||||
@@ -65,7 +67,9 @@ async def get_projection(
|
||||
pd_repo: PersonalDataRepositoryDep,
|
||||
workspace_repo: WorkspaceRepositoryDep,
|
||||
vacation_repo: VacationDaysRepositoryDep,
|
||||
scope: WorkspaceScopeDep,
|
||||
) -> WorkspaceOverviewResponse:
|
||||
await scope.check_child(child_id)
|
||||
service = _make_service(
|
||||
leave_repo, planned_repo, child_repo, pd_repo, workspace_repo, vacation_repo
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ from app.dependencies import (
|
||||
ChildRepositoryDep,
|
||||
CurrentUserDep,
|
||||
PersonalDataRepositoryDep,
|
||||
WorkspaceRepositoryDep,
|
||||
)
|
||||
from app.rate_limit import limiter
|
||||
from app.models.auth import LoginRequest, RegisterRequest, TokenResponse, UserMeResponse
|
||||
@@ -105,6 +106,11 @@ class _UserContext(BaseModel):
|
||||
workspace_id: str
|
||||
parent_name: str
|
||||
children: list[_ChildContext]
|
||||
# Mirrors `WorkspaceResponse.take_pl_on_red_days` — included here so the
|
||||
# frontend's cold-load `refreshContext()` can build its `workspace`
|
||||
# state from this response alone, without a follow-up `GET
|
||||
# /workspace/:id` (see AGENTS.md H12 step 1).
|
||||
take_pl_on_red_days: bool
|
||||
|
||||
|
||||
@router.get("/context", response_model=_UserContext)
|
||||
@@ -112,12 +118,16 @@ async def get_context(
|
||||
current_user: CurrentUserDep,
|
||||
pd_repo: PersonalDataRepositoryDep,
|
||||
child_repo: ChildRepositoryDep,
|
||||
ws_repo: WorkspaceRepositoryDep,
|
||||
) -> _UserContext:
|
||||
"""Return workspace + children for the current user. Used by the dev harness."""
|
||||
pd = await pd_repo.get_by_id(current_user.personal_data_uuid)
|
||||
if pd is None:
|
||||
raise HTTPException(status.HTTP_422_UNPROCESSABLE_CONTENT, "No parent profile found")
|
||||
children = await child_repo.list_by_workspace(pd.workspace_id)
|
||||
workspace = await ws_repo.get_by_id(pd.workspace_id)
|
||||
if workspace is None:
|
||||
raise HTTPException(status.HTTP_422_UNPROCESSABLE_ENTITY, "No workspace found")
|
||||
return _UserContext(
|
||||
personal_data_uuid=str(pd.uuid),
|
||||
workspace_id=str(pd.workspace_id),
|
||||
@@ -125,6 +135,7 @@ async def get_context(
|
||||
children=[
|
||||
_ChildContext(id=str(c.id), name=c.name, birth_date=str(c.birth_date)) for c in children
|
||||
],
|
||||
take_pl_on_red_days=workspace.take_pl_on_red_days,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user