fix(email): correct OAuth post-auth redirect (404 after reconnect) - #6
Merged
Conversation
redirect_after was double-encoded: handleConnect wrapped window.location.href in encodeURIComponent and then URLSearchParams encoded it again. Only one decode happened downstream, so the callback received a literal "https%3A%2F%2F…" string and router.push treated it as a relative path → /email/oauth/https%3A%2F%2F… → 404. - integrations EmailTab: pass window.location.href raw (URLSearchParams encodes once). - oauth callback: normalise redirect_after to a safe same-origin path via new URL(); reject cross-origin / unparseable values (open-redirect guard) and fall back to /email. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vjvarada
added a commit
that referenced
this pull request
Jul 13, 2026
… version (BO-12 / BO-19) AGENTS.md described a runtime reality that no longer holds: - "MAF is the sole runtime; Copilot SDK is mutation-sandbox only" (#6) was false — the Copilot SDK is a first-class interactive chat runtime (Tier 1.5, /copilot/chat, BYOK-routed). Reconciled the runtime line, Purpose, and non-negotiables #6/#9 to reflect this while keeping "MAF is primary/preferred for event-driven specialist execution" (closes H6). - Removed the unused `WorkflowBuilder` import + its "used for multi-step pipelines" docstring claim in orchestrator/agents.py — it was imported but never instantiated (closes M2). `as_tool()` is genuinely used; that claim stays. - BO-19: "Python 3.11+" → "3.12+" to match pyproject (>=3.12,<3.14) and CI/prod. Docs + one dead-import removal; agents.py compiles, CI correctness gate clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vjvarada
added a commit
that referenced
this pull request
Jul 18, 2026
…pt1) First slice of #6 (calendar_ux_review §3 P3 / §4) — the data foundation for the trust/accuracy flywheel. We stored the PLAN (scheduled_*) and the GUESS (time_estimate_mins) but never what actually happened. - actual_start / actual_end on gtd_items (mig 80, additive) — threaded through GtdItemModel/_row_to_item/ItemPatch and types/api/store. - Focus timer: a "Start" on the Now bar's current block stamps actual_start; the running block shows a live "▶ 12m" and a pulsing progress bar. - Completing a STARTED block stamps actual_end (reopening clears it), so we capture real work-time only for timed sessions — no fabricated data. - Completed blocks show planned-vs-actual as a glanceable delta: "+15m" (warning, ran long) / "−10m" (success, under) / "on time", full detail on hover. The estimate-accuracy signal, per block. Refactor: folded the six timestamp columns (defer/due/scheduled/actual) in _build_item_update into one data-driven loop instead of a branch each — so adding a dated field no longer grows this translator's complexity (in fact drops it 18→16, below its grandfathered baseline). Behaviour-identical. Deferred to #6 pt2: the end-of-day review surface + learned estimates (per-user fudge factor from these actuals). tsc+eslint+build clean; py_compile+ruff clean re: my changes (pre-existing I001 untouched). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vjvarada
added a commit
that referenced
this pull request
Jul 18, 2026
Closes #6 (calendar_ux_review §3 P3 / §4) — the actuals captured in pt1 now feed the trust/accuracy flywheel. LEARNED ESTIMATES. GET /calendar/estimate-stats returns the median actual/planned duration ratio over the user's recent (90d) completed TIMED blocks — the "you take 1.3x your estimate" fudge factor. The planner applies it: /calendar/plan pads every candidate duration by the clamped ratio (0.8–1.75, only with ≥5 samples) so a chronic under-estimator gets a realistic day, and says so in its notes. Extracted _estimate_ratio / _estimate_pad / _join_notes helpers so plan_day's complexity is unchanged. END-OF-DAY REVIEW. A new EndOfDayReview modal (header "Review" button, shown when there's activity scheduled today): an at-a-glance done/carry-forward tally, the estimate-accuracy line (or a "hit ▶ Start to learn" tip when there's not enough signal yet), a celebrated DONE list with planned-vs-actual deltas, and a kindly-framed "carry forward" list (not a wall of red). Client computes today from the store; only the accuracy stat is fetched. apiEstimateStats + EstimateStats on the client. Backend ruff-clean (fixed the ambiguous ×→x); tsc+eslint+prod build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Why
After the reconnect flow added in #5, completing OAuth redirected to
/email/oauth/https%3A%2F%2Fcommandcenter.fracktal.in%2Fintegrations→ 404.redirect_afterwas double-encoded (encodeURIComponent+URLSearchParams), decoded only once downstream, so the callback pushed an encoded string as a relative path.What
integrationsEmailTab: passwindow.location.hrefraw (URLSearchParams encodes once).redirect_afterto a safe same-origin path vianew URL(), reject cross-origin/garbage (open-redirect guard), fall back to/email.The account reconnect itself already worked — verified on prod:
sync_status=idle, 100 messages now underinbox. This only fixes the cosmetic post-auth 404.Verification
tsc --noEmit: clean on both edited files.🤖 Generated with Claude Code