60 Commits
Author SHA1 Message Date
Thomas DurieuxandClaude Opus 5.5 476f25e264 feat(ui): browse and check every file in the anonymize preview (#950)
* feat(ui): browse and check every file in the anonymize preview

The "What reviewers will see" window now redacts the README GitHub actually
shows and lets authors open any file of the commit.

- README: resolved from the file list like GitHub (.github/, root, docs/,
  any case, Markdown first) and only that path is tested against the
  "Leave files unredacted" rules. Before the list loads, only root names are
  assumed, so leaving docs/ unredacted no longer unredacts the root README.
  The file bar shows the README's real name.
- New GET /api/repo/:owner/:repo/file?commit=&path= (same access checks as
  /tree): raw text, no-store, path traversal rejected, 1 MB cap
  (file_too_big, 413), binary files reported as { binary: true }.
  /tree also lists binary files (binaryFiles) for the preview's tree.
- Tree rows open files (keyboard accessible, explorer active rail). Text is
  redacted through /api/anonymize-preview by the same batcher as the README;
  files left unredacted are sent without terms and tagged "Left unredacted"
  (opens the dialog). Markdown renders like the README, code is highlighted
  with Prism, images/PDF/binary/too-large files get a short note. Loading
  and error (Retry) states reuse rp-state.
- File and folder names are redacted through /api/anonymize-preview.
- Caption counts the open file; "<name> left unredacted" when preserved.
- Phones: the Files button opens the tree as a sheet.
- dev-mock: a jsmith/robust-repair source with tree, file and
  anonymize-preview endpoints and fixtures carrying the mock's terms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): reuse the explorer in the anonymize preview

Share the explorer file renderer and tree with the author preview. Apply
preserved-file rules on the server and keep the reviewer rendering and
redaction slots consistent across both views.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep the reviewer page unchanged by the preview reuse

The preview reuses tree.js and the shared file viewer; its differences now
apply only inside the anonymize preview.

- The narrow-pane rule that hid the file meta and Symbols applied to the
  reviewer page too (visible with a widened sidebar); it is scoped to
  .reviewer-preview. The token capture moves from body to the page that
  holds the preview.
- tree.js: aria-expanded/aria-current and tree-only scrolling apply only
  when the tree is embedded (selectedPath set); the reviewer page keeps
  scrollIntoView and its original markup.
- file-viewer: the extra menu-closing click listener, the #L hash writes and
  the Ctrl+F/G and Alt+Z shortcuts are limited to the preview (shortcuts
  only while its code has focus), so the form keeps the browser's Find.
- Preview: the tree's file list is cached between renders, name batches are
  chunked under the JSON body limit, /api/anonymize-preview accepts up to
  3 MB so files up to the 1 MB preview limit can be redacted, and on phones
  the caption's "<name> left unredacted" opens the dialog (the header tag
  squeezed the path out).
- dev-mock: long and nested names for the tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): restore the redaction number on the right and level the slots

The redesign centered the term number in every redaction slot; it sits on
the right edge again, in code, Markdown, the tree and the breadcrumb. Tree,
breadcrumb and paragraph slots also sat about 2px below the text; they now
center on the line's letters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: address preview navigation and path review findings

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 14:27:13 +01:00
Thomas DurieuxandClaude Opus 5.5 6226acff80 fix(ui): show a vertical file tree in the reviewer preview
The "What reviewers will see" window now has a sidebar like the explorer's
instead of the one-row file strip: folders first, then files, with the
explorer's tree rows, icons and teal selection on the README. Folders expand
from the loaded file list. The sidebar is 24% of the window (180-240px),
tinted full height, and scrolls apart from the document. Phones hide it and
show the explorer's "Files" button in the file bar. Loading shows skeleton
rows; without a file list the sidebar shows the README only.

Removes the strip fitter and the dead rail/strip CSS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 03:54:56 +00:00
Thomas DurieuxandClaude Opus 5.5 7423c78e27 fix(ui): follow-ups after the redesign
- Tabs: one indicator for every tab bar (admin, settings, dashboard,
  conference, PR/gist viewer, error detail, workspace phone tabs, home
  steps): a straight 2px accent line as wide as the label, on the bar's
  bottom rule. Hover changes only the label colour. The phone admin nav
  is one scrolling row.
- Header: nav labels never wrap. Signed in, "Report a bug" and "Support"
  move to the avatar menu below 1366px, gaps tighten below 1100px, and a
  fitter applies the same steps whenever the bar still overflows (wider
  fonts, Upgrade link, long usernames).
- Dashboard: 12px between the search row and the active filter chips;
  "Load more projects" sits 20px under the table, centred.
- Reviewer preview: the file strip is one row (folders first, README
  always shown, then "+N more") instead of wrapping every top-level entry.
- Workspace footer: the submit button keeps its width and never clips; the
  draft note beside it wraps. The bar uses the fields' 20px inset.
- Auto-update: without an allowance that includes automatic updates, the
  checkbox shows a Paid tag and the Live updates price, and the hosting
  section explains how to add it. #946's hosting message for this case
  could never show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 03:38:30 +00:00
Thomas DurieuxandClaude Opus 5.5 c044b83541 feat(ui): one consistent design across author, reviewer and admin screens
The UI was uneven: the home page looked finished, but app pages used three
different display typefaces, the anonymize flow changed frame between steps,
and the dashboard, explorer and admin screens each had their own controls,
status colours and edge-case handling.

Make every screen follow one system: shared page header, grid, buttons,
filters and status colours; a repository picker and step trail on anonymize;
a "What reviewers will see" preview of the actual reviewer page; consistent
file headers and viewers for every file type; truthful admin charts and
tables. Fold the accumulated override blocks back into style.css (22%
smaller, no visual change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 02:22:45 +00:00
Thomas DurieuxandClaude Opus 5.5 d25e5336ce feat: let authors pay once per paper instead of subscribing
Most authors use the service for one paper a few times a year, so a
subscription does not fit. Add cheap one-time options (Paper pack, Extra
repository, Live updates, Extended expiration, Never expire), cap free
dated expiration at 5 months, keep cheaper subscriptions for heavy users,
and make every new conference a paid review package in three sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 16:04:31 +00:00
Thomas DurieuxandClaude Opus 5.5 643f4b87e9 feat: let authors leave their bibliography unredacted (#941) (#943)
* feat: let owners leave chosen files unredacted (#941)

Redacting self-citations in a bibliography reveals which papers are the
authors' own. Owners can now pick files whose content is served as
written; file names are still redacted. Patterns follow .gitignore rules.

The form gets a file picker fed by GitHub's tree API, and the terms box
grows with its content and only warns about regex symbols that can stop a
term from matching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: honour !patterns, keep picked braces literal, preview unredacted README

- Patterns now apply in order and the last match wins, as in .gitignore,
  so "*.bib" then "!private.bib" excludes private.bib instead of
  preserving every other file.
- Picked paths escape glob characters, braces included, with a
  backslash; "[{]" did not survive brace expansion.
- The README preview drops terms when the README is an unredacted file,
  and refreshes when the list changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep rule order when deduplicating unredacted-file patterns

Rules apply in order and the last match wins, so dedupe keeps the last
copy of a repeated pattern instead of the first. The picker also keeps a
plain path in its place when it follows another rule, rather than moving
it to the front as a pick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: apply unredacted-file rules to folders, as in .gitignore

A rule that matches a folder now covers every file inside it, so "*.bib"
then "!private" keeps private/refs.bib redacted. A trailing "/" limits a
rule to folders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: folder unchecks win over broad rules; accept short commit hashes

- Unchecking a folder that a broader rule such as "*.bib" still covers
  appends a "!/folder/" exclusion, so its files really go back to being
  redacted.
- The tree endpoint accepts the 6+ character hashes the commit field
  allows and resolves them to a full SHA before reading the tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: picker counts folder rules exactly as the server does

Rules ending in "/" stay patterns instead of being read as picked files,
and the checkboxes now run the saved rule list (picks, then patterns)
through the server's matcher, so the dialog cannot show files as
redacted that the server leaves unredacted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: insert escaped terms literally in "Match as written"

String.replace expanded "$&", "$'" and "$1" in the term, so the fix
could corrupt the line. Splice by index instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:10:54 +01:00
Thomas DurieuxandClaude Opus 5.5 5bad2a2597 fix(ui): mobile viewer, code-block redactions and anonymize preview
- Anonymize preview renders redactions as the viewer's numbered slots
- Code-block slots keep the width of XXXX-n and sit on the text line
- README no longer overflows on phones (grid forced two columns)
- Status bar always hides under the file header: no second Files button
  or breadcrumb on repos with a website or for owners; Open website and
  Edit anonymization move to the file menu
- Loading state no longer repeats the path visually
- Phone usage popover opens inside the screen
- Home closing band: no double divider, tighter gap above the footer
- File drawer closes after opening a file on phones

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:29:50 +00:00
Thomas DurieuxandClaude Opus 5.5 c685d833ab Merge origin/main into feat/ui-redesign
Backend, scripts, docs and their tests take main's newer code where both
sides changed the same lines (the shared blob cache, GitHubStream and
markdown fixes landed on main after the Go migration branch was cut).
The Dockerfile keeps the Go build from the migration, plus main's
owner-alert-protocol label; .gitignore keeps both sides' entries.

Frontend keeps the redesign and folds in main's features: Stripe billing
in the New anonymization submit bar, GitHub access repair, redaction
syntax help, the preview expand toggle, configurable redaction mask,
folder counts, reviewer-route header rules, link expiry (now in the
viewer's snapshot details) and the explorer error card. main's
narrow-only wrap logic is dropped because the redesign wraps on desktop
and scrolls sideways on phones.

Tests: 1534 passing with SESSION_SECRET set (as in CI). Three main tests
were updated for the agreed viewer design (no site header in the viewer,
no repository-wide file count).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 14:07:33 +00:00
Thomas DurieuxandClaude Opus 5.5 53cac6ac39 feat(ui): follow-up polish from design review rounds 88-91
One-row phone toolbar, errors page opens on server errors, one-row submit
bar, publish warning after a source loads, three-column FAQ with a help
card, queue range control in the Throughput card, shared admin table cards,
dark-mode contrast and a stronger phone code scroll cue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 13:36:59 +00:00
Thomas DurieuxandClaude Opus 5.5 579ce970c7 feat(ui): redesign the viewer, landing, author and admin screens
Viewer: full-height app bar with a Help menu, search + ZIP sidebar, one
toolbar for README and code, reading mode with a scroll-tracking outline,
docked find for Markdown and code, and redaction slots (a blank stone slot
holding the term number) in prose, headings, code, the tree and the path.

Landing and FAQ: live redaction demo, serif display headings, teal accent.

Author screens: My work table with copy/open/edit actions, a usage meter,
a single-container New anonymization flow with a sticky submit bar, themed
form controls, and consistent GitHub connection cards.

Admin: underline tabs, severity-first errors chart and list, error tiles
that filter (older pages load until matches appear), queue and overview
health states, and shared toolbar heights and borders.

Fixes: guarded localStorage access, failed README images render a
placeholder, phone hover states no longer stick, and UI tests updated for
the new copy and markup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 10:52:10 +00:00
Thomas Durieux ded6f905fd merge: reconcile paid hosting with latest main 2026-11-02 21:12:29 +00:00
Thomas Durieux 410863d253 feat: add paid author and conference hosting with Stripe 2026-11-02 20:49:03 +00:00
Thomas Durieux 075c3a4622 Suggest existing configurations for duplicate repository URLs (#911) 2026-11-02 06:31:57 +00:00
Thomas Durieux 8ce670a613 fix: show repository authorization controls for App-only users (#894) 2026-10-12 19:47:04 +01:00
Thomas Durieux 1d326e7c32 fix: repair private repository access from the edit page (#892)
* fix: repair private repository access from the edit page

* fix: respect App rollout and reload renamed sources after repair

* fix: gate access repair by status and update response tests
2026-10-11 12:13:02 +01:00
Thomas Durieux db966356ec fix: support gists through GitHub App login (#875)
* fix: prompt OAuth reconnection when gist credentials are rejected

* fix: support gist reads through GitHub App user grants

* test: adapt truncated gist regression to provider selection

* fix: address gist reconnect visibility and token renewal review

* fix: verify App authorization before revoking OAuth
2026-10-08 10:26:13 +01:00
Thomas Durieux 282efdc16e fix: make dashboard UI consistent and compact on mobile 2026-10-07 14:54:49 +00:00
Thomas Durieux d28799f234 fix: reconnect anonymizations to recreated source repositories 2026-09-29 23:09:51 +00:00
tdurieux 99a50cad7b feat: unify GitHub sign-in and connect OAuth for gists 2026-09-10 18:20:56 +02:00
tdurieux 68d9c54fcf fix: keep GitHub access controls beside the source URL 2026-09-10 18:04:56 +02:00
tdurieux df81d7db56 style: restore mobile sign-in and compact access controls 2026-09-10 16:07:02 +02:00
Thomas Durieux a60ad6a921 feat: add read-only GitHub App access alongside OAuth 2026-09-09 22:08:12 +02:00
tdurieux 8e85458b05 fix: unblock gist and pull request form submissions 2026-09-09 13:41:20 +02:00
tdurieux 4a18f94631 refactor: migrate the frontend from AngularJS to Vue 3 2026-09-09 13:19:53 +02:00
tdurieuxandClaude Fable 5.1 a02e83e48c feat: clarify the menus and rework the settings page
"Report an issue" in the navbar read like a way to report an anonymized
repository, and it opened a blank GitHub issue instead of the template
that asks reporters to confirm the issue is about the service. The user
menu offered "Default settings" and "Logout" with no hint of what lives
behind them, and the Claim page was unreachable from any menu.

The settings page never loaded quotas (the bars stayed in their striped
loading state), mixed serif checkbox labels with sans forms, used
Bootstrap alert colours, and described options in jargon ("Proxy mode",
"Github page", "Line of code").

- Navbar: "Report a bug" links to the issue template with a tooltip that
  names the service; the user menu shows who is signed in and lists
  Settings, Claim an anonymization, Report a bug, Source code, Sign out,
  each with a one-line hint. Icon links get aria-labels.
- Settings: quotas load through a shared quotaService (also used by the
  dashboard); sections match the side navigation, which now follows
  scrolling via a small paperScrollspy directive; copy explains each
  option; account card with Sign out; delete moved into a danger zone;
  Save shows Saving/Saved and the error alert uses the paper palette.
- Conferences list and detail: sort and status buttons show their state,
  hidden statuses appear as chips with a count line, Remove is a button
  behind a divider, dates spell the month, expiry column matches the
  dashboard, detail page gets an Edit button and plan/cost meta.
- New conference: validation errors only appear after a field is touched
  or the form submitted; pricing copy matches how price is computed.
- Status page: progress label no longer overlaps the details below it;
  "Report a bug" points at the template and says whom it is for.
- Claim: single rule, constrained width, explains when to use it.
- Anonymize: shorter placeholder, consistent Auto-update label.
- Mock server gains the endpoints these pages need and an ANON mode.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 20:55:22 +02:00
Thomas DurieuxandClaude Opus 4.8 5ef10dee9e fix: dashboard menu clickability + expiration date UX (#753)
* fix: dashboard menu clickability + expiration date UX

Dashboard actions menu:
- Inactive (expired/removed) rows dimmed via their cells instead of the
  row, so `opacity` no longer creates a stacking context that trapped the
  actions dropdown beneath later rows and made its items unclickable.
- Add an "Extend 6 months" menu item for expired repos/PRs/gists.

Expiration form (anonymize):
- Fix the "After , the content will be removed." blank date: guard the
  helper text and add min/max validation feedback so an invalid pick no
  longer nulls the model into a broken sentence.
- Add a `min` (today) so past dates can no longer be selected, and
  compute min/max from local date parts (not UTC) to avoid a timezone
  off-by-one in the native picker.
- Default expiration is now 6 months (single source of truth, removing a
  latent double-offset bug); max stays at 1 year.
- Block submitting a missing/out-of-range expiration date.

Backend:
- New POST /:id/extend endpoint for repos, PRs and gists that pushes the
  expiration +6 months and re-anonymizes so expired items come back
  online, mirroring the refresh flow. Shared extendExpirationDate helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: add frontend translation for invalid_status error code

The new /extend endpoints throw an "invalid_status" AnonymousError, which
the error-code coverage test requires to have a locale entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 14:10:38 +02:00
tdurieux 1edc9b7221 fix: remove never expiration 2026-07-02 15:06:12 +03:00
tdurieux d9104c2ec2 Update commit on branch refresh and validate commit exists on save
Refresh button now always updates the commit to the latest SHA instead
of preserving the stale one in edit mode. Both create and update routes
verify the commit still exists on GitHub before persisting.
2026-05-06 21:14:53 +03:00
tdurieux c1e18f82a9 Improve error handling 2026-05-06 17:39:43 +03:00
tdurieux dee406e2ea update design 2026-05-05 00:36:42 +03:00
tdurieux f0bc53f093 feat: gist & co-authors 2026-05-04 13:10:44 +02:00
tdurieux c8fc561dac fix: regex characters in terms shouldn't block submission
Entering an IP address (e.g. 192.168.1.1) or any term with regex
metacharacters made the form invalid because the "regex characters
detected" hint was wired up via $setValidity('terms', 'regex', false).
The text in the UI labels it as a warning, but the form treated it as
an error and refused to save.

Track the warning as a plain $scope flag and show it via ng-show on
that flag, so the form stays valid (#430).
2026-05-04 10:58:17 +02:00
tdurieux 4bc83db416 feat: per-term anonymization output via term=>replacement
A term entered as "Anonymous=>ABC" now scrubs "Anonymous" to "ABC"
instead of "XXXX-N". Lets users keep anonymized identifiers valid in
source code (no hyphen) and align tokens between paper text and repo.
Indexing for default-mask terms is unchanged: a list of
"Alpha=>AAA", "Beta" still produces XXXX-2 for Beta.

Fixes #285.
2026-05-04 09:31:31 +02:00
tdurieux a5f66d6844 multiple fixes 2026-05-03 15:30:54 +02:00
tdurieux 88f826aab4 update design 2026-04-24 14:55:18 +02:00
Thomas DurieuxandClaude 3f32ec5ca1 claude/fix-page-width-layout-SY7c5 (#679)
* Fix horizontal overflow causing page content to be cut off on mobile

- Add overflow-x: hidden to html/body and ng-view to prevent horizontal
  scrolling across all pages
- Restore .container.page mobile padding to 15px to match Bootstrap .row
  negative margins (-15px), which previously caused 5px overflow per side
- Add max-width: 100% constraints to prevent content from exceeding viewport

https://claude.ai/code/session_01L2xhJCKkjghMDBuwXpSHzi

* Fix Ko-fi widget overlapping hamburger menu and simplify desktop layout

- Move Ko-fi "Support me" button from top-right (where it hid the navbar
  hamburger) to bottom-right corner
- Remove card styling (border, background, border-radius) from dashboard
  quota section for a flatter, cleaner look
- Remove fixed max-width: 960px from dashboard-page so it uses Bootstrap's
  standard container widths, consistent with other pages like admin

https://claude.ai/code/session_01L2xhJCKkjghMDBuwXpSHzi

* Redesign anonymize page: centered landing, reorganized form layout

- No URL state: centered input in the middle of the page for a clean
  initial experience
- URL provided state: preview on the left, form settings on the right
  in a fixed-width sidebar panel (380px on desktop)
- Reorganized form sections into logical groups:
  Source (branch/commit) → Identity (ID/conference) → Anonymization
  (terms) → Display (checkboxes, no longer hidden in accordion) →
  Expiration
- Removed card/accordion wrappers for a flatter, more scannable form
- Mobile: form stacks below preview with sticky submit bar

https://claude.ai/code/session_01L2xhJCKkjghMDBuwXpSHzi

* Reduce navbar height on desktop

- Reduce navbar padding from default .5rem to 4px vertical
- Shrink nav icons from 30px/40px to 20px/28px
- Reduce nav-link font size to 0.9rem with tighter padding
- Shrink navbar-brand font size to 1rem

https://claude.ai/code/session_01L2xhJCKkjghMDBuwXpSHzi

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 11:13:05 +02:00
Thomas Durieux 261eaa8d79 Polish website UX: unify dashboards, clean up layout, modernize styling (#668) 2026-04-15 09:30:19 +02:00
Thomas Durieux 1d97c76e7e Improve mobile layout and redesign admin interface (#665) 2026-04-15 06:04:43 +02:00
tdurieux e94a5f164a disable download mode for the moment 2023-04-05 12:12:57 +02:00
tdurieux 692ea33b5d feat(#162): add warning message when regex charater is detected inside terms 2023-02-03 16:22:19 +01:00
tdurieux 5c3d358a25 fix: fix GitHub page settings 2022-08-10 08:35:57 +02:00
manathan1984 1469ebb092 fix: add "ID" next to "Conference" (#82) 2021-09-12 00:25:31 +02:00
tdurieux f17454b919 fix: fix anonymization page 2021-09-12 00:07:11 +02:00
Thomas Durieux 6056605b85 chore: improve anonymization form (#81) 2021-09-09 14:30:34 +02:00
tdurieux b3a7278819 fix: fix repository selection 2021-09-06 11:59:59 +02:00
Thomas Durieux 49da267d5f feat: Add conference manager (#71) 2021-09-06 09:34:39 +02:00
tdurieux cde9214579 fix configuration issue during anonymization 2021-08-24 09:35:48 +02:00
tdurieux 28075889a6 fix: fix repository update 2021-08-20 16:01:10 +02:00
tdurieux caeff49ab0 migrate JavaScript to TypeScript 2021-08-13 08:26:23 +02:00
tdurieux dc84de9d84 improve error message 2021-04-27 08:01:02 +02:00