Commit Graph
276 Commits
Author SHA1 Message Date
tdurieux 8e85458b05 fix: unblock gist and pull request form submissions 2026-09-09 13:41:20 +02:00
tdurieux e68ab037eb perf: load document libraries only when needed 2026-09-09 13:28:44 +02:00
tdurieux 4a18f94631 refactor: migrate the frontend from AngularJS to Vue 3 2026-09-09 13:19:53 +02:00
Thomas Durieux dc0ef022fb Merge pull request #810 from tdurieux/feat/landing-redesign
feat: rebuild the landing page around the product
2026-09-09 12:24:47 +02:00
tdurieuxandClaude Fable 5.1 88d8225f00 feat: rebuild the landing page around the product
The home page led with a text hero, a boxed stats strip, a numbered
how-it-works list, a trust card and three Bootstrap featurettes with
postage-stamp screenshots. It now shows the product first and stays
flat:

- Hero: copy on the left, the anonymize form in a browser frame on the
  right, one primary CTA plus a link to a real anonymized repository,
  and three reassurance points (free, read-only, expires).
- Proof and live stats collapse into hairline strips with no cards;
  the stat bars keep their daily-delta charts and the "+N today" line.
- Before/after example gets a section head and shows the actual XXXX-n
  masks, each labelled for screen readers.
- "What you get" is one large screenshot with three vertical tabs
  (Anonymize, Review, Manage) instead of three columns. Tabs are real
  buttons with tablist/tab/tabpanel roles, roving tabindex and arrow-key
  navigation; the description and link sit outside the button. Signed-out
  visitors are sent to sign in rather than to a dashboard that redirects.
- FAQ teaser with the three questions that come up most, linking into
  the FAQ anchors.
- Phone layout: tabs become a strip above the screenshot with the
  selected description below it, stats go two-up, panes stack, the CTA
  fills the width, and horizontal overflow is clipped so the hero bleed
  can never cause sideways scrolling.

Removes the dead how-it-works, trust, featurette and metrics styles and
the legacy mobile hero font overrides that fought the new sizes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 12:21:02 +02:00
Thomas Durieux f27e9ca9a0 Merge pull request #809 from tdurieux/feat/dashboard-redesign
feat: make the dashboard, menus and settings readable at a glance
2026-09-08 21:07:30 +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
tdurieuxandClaude Fable 5.1 8e9b5b9a45 feat: make the dashboard readable at a glance
The dashboard showed the anonymize date under "Expired", a dash in the
Expires column for 54 of 60 rows, raw status codes such as
branch_not_found, and a chip reading "REMOVED" that actually meant
"removed items are hidden". Muted text sat at 3.5:1 contrast, keyboard
focus was invisible, numbers were left-aligned, and a legacy record
without an identifier rendered as an empty link to /pr/undefined/.

This rewrites the dashboard template and controller and tightens the
theme tokens:

- Status sub-line is labelled ("anonymized on Sep 6, 2026"); Expires
  shows Never, the date, or "Expired on <date>".
- Conference folded into the name cell as a tag; Views right-aligned;
  every column header is a keyboard-sortable button with aria-sort.
- Sort/Status buttons show their state; chips read "Hiding Removed";
  result count and Clear filters; empty state with a way out.
- Status filter covers Ready, In progress, Error, Expired, Removed.
  Stuck downloads say so; codes map to sentences; statuses to labels.
- Lists load in parallel and merge once behind a skeleton; broken
  records are flagged instead of linking nowhere.
- Actions menu: View, View page, Edit, Force update, divider, Remove,
  all as buttons rather than href="#" anchors.
- Theme: warm dark canvas, muted text >= 4.5:1 in both modes, semantic
  status tokens, 11/13/14/16px type scale, mono only for identifiers,
  6px/10px/pill radii, :focus-visible ring, quota bars in ink until a
  limit is near, unlimited shown as such.
- Mobile: no 9px text, filter row wraps in two lines, meta on one line.

Adds scripts/dev-mock.js to serve the dashboard with fixture data and
test/dashboard-ui.test.js covering the filters, template invariants and
token contrast.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 20:20:17 +02:00
Thomas Durieux 530e388e46 fix: archive ownerless repositories without assigning ownership (#800) 2026-09-08 14:03:09 +02:00
tdurieux 9f00641529 fix: preserve the year in default conference end dates 2026-09-06 10:47:59 +02:00
tdurieux 681f72f75c fix: inject the translator for profile save errors 2026-09-06 10:47:53 +02:00
tdurieux 793e926463 fix: cancel status polling when the view is destroyed 2026-09-06 10:47:47 +02:00
tdurieux cac76ad7b6 fix: select the PR diff tab after content loads 2026-09-06 10:47:32 +02:00
tdurieux 5c6e5b6519 fix: anonymize PR comment authors and bodies in previews 2026-09-06 10:47:26 +02:00
tdurieux 66e4be0a0c fix: reload PR and Gist views when resource IDs change 2026-09-06 10:47:20 +02:00
tdurieux a6e17e18d9 fix: clear failed searches without racing subsequent requests 2026-09-06 10:47:09 +02:00
tdurieux a27f9f34d6 fix: reload explorer state when repository identity changes 2026-09-06 10:47:03 +02:00
tdurieux b6c0d3a8ed fix: ignore stale file responses after viewer navigation 2026-09-06 10:46:57 +02:00
tdurieux b2dfda1838 fix: sanitize Org previews before trusting rendered HTML 2026-09-06 10:46:44 +02:00
tdurieux cf58aa330b fix: handle prototype property names in repository trees 2026-09-06 10:46:38 +02:00
tdurieux d793d2c7c6 fix: bind file tree names without compiling repository content 2026-09-06 10:46:32 +02:00
tdurieux 5e84bfaa5b fix: surface partial S3 object deletion failures 2026-09-06 09:18:32 +02:00
tdurieux 11eb160d2b fix: prevent stale downloads from reviving removed repositories 2026-09-06 09:17:33 +02:00
Archit Rastogi 420fa9e450 fix: clip overflowing conference link in dashboard table (#790)
The Conference cell is a grid item with the default min-width:auto,
so a long unbroken URL forces the grid track wider than its
minmax(140px, 1fr) size and bleeds visually into the Status column.
Clip it with overflow:hidden/ellipsis and expose the full value via
a title attribute.
2026-08-26 21:47:23 +02:00
Thomas Durieux 74ed0c6d51 fix: keep route overflow out of the page body (#785) 2026-08-20 14:52:45 +02:00
tdurieux 44842d4e77 fix: handle navigation inside the app 2026-08-06 15:02:40 -07:00
tdurieux f0fdd9250b fix: improve pdf rendering and html 2026-08-06 14:35:21 -07: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
Thomas Durieux 839582c657 Fix .bat anonymization, truncated-tree misses, submodule warning, account deletion (#742)
* fix: anonymize Windows batch scripts (#735)

mime-types maps .bat to application/x-msdownload, the same MIME type as
.exe/.dll, so batch scripts were classified as binary and streamed
through without any anonymization. Special-case .bat/.cmd as text before
the MIME lookup, keeping .exe/.dll binary.

* fix: recover files missing from truncated tree listings (#738)

GitHub truncates tree listings of very large repositories. Folders whose
listing was truncated are recorded in truncatedFolders, but files that
fell outside the listing never reached the database, so requesting them
returned 404 file_not_found even though they exist on GitHub — and a
force refresh could not help.

When a file lookup misses and its directory is under a truncated folder,
fetch the file metadata directly from GitHub's contents API (object
media type, so it works past the 1MB inline limit), cache it in the
database, and serve it normally.

* feat: warn when a repository uses git submodules (#737)

GitHub archives and tree listings never include submodule contents, so
submodules end up as empty folders in the anonymized repository, which
surprises users. Detect a root .gitmodules file and show a warning
banner in the explorer explaining that submodule contents are not
included.

* feat: allow users to delete their account (#741)

Add DELETE /api/user: removes all anonymized repositories, gists, and
pull requests owned by the user, best-effort revokes the GitHub OAuth
grant, and scrubs personal data (username, emails, tokens, GitHub id,
photo) from the user record. The record itself is kept with a
placeholder username so removed repoIds stay reserved and owner
references remain resolvable.

The settings page gains an Account section with a confirmed delete
button.

* fix: add missing error translations for token_expired and job_is_active

The error-code coverage test failed because both backend codes had no
frontend translation.
2026-07-02 13:35:48 +02:00
Thomas DurieuxandClaude Opus 4.8 e4ffd74068 Security hardening + gist UI fixes (#731)
* security: harden against XSS, ReDoS, path traversal, and injection

Defensive fixes across the server, storage, and viewer:

- XSS (CWE-79): sanitise rendered notebooks with DOMPurify, escape file
  names interpolated into AngularJS expressions (escapeNgString), set
  Mermaid securityLevel to 'strict', and stop urlRel2abs from returning
  javascript:/vbscript:/data:text/html URLs.
- Path traversal / zip-slip (CWE-22/23/24): validate URL-derived path
  components before they reach the storage layer (file/webview routes +
  StorageBase.assertSafePath) and sanitise zip entry names on extract for
  both the filesystem and S3 backends.
- ReDoS (CWE-1333): escape anonymization terms with catastrophic
  backtracking shapes to literals instead of compiling them as regexes.
- Secret hardening (CWE-798): require SESSION_SECRET / OAuth creds / DB
  password in production, random dev SESSION_SECRET fallback.
- Rate-limit spoofing (CWE-290): derive request.ip via trust-proxy hop
  count instead of the client-settable cf-connecting-ip header.
- NoSQL injection (CWE-943): allow only plain field paths as admin sort keys.
- Reject malformed streamer requests missing required string fields.

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

* fix(ui): make gists reachable/visible and clarify the ZIP button

- Gist & PR routes now accept a trailing slash (/gist/:id/:path*?), so the
  dashboard links (which end in "/") resolve to the gist/PR page instead of
  falling through to the 404 route (#725).
- Gist viewer picks the default tab after content loads, defaulting to
  "files" when files exist; previously the ng-init ran before the async
  load and a files-only gist rendered blank under the hidden comments tab.
- Explorer toolbar: relabel ZIP to "Full repo ZIP" with a tooltip, and add
  tooltips to Raw/Download clarifying they apply to the current file (#721).

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

* fix: report SAML-enforced orgs clearly instead of "token expired"

When a repo's organization enforces SAML SSO, GitHub returns a 403 whose
message differs from the OAuth-App-restriction case. That 403 fell through
to the generic handler and surfaced as "token_expired", pushing users to
re-login when the real fix is authorizing their token for the org. Detect
the "SAML enforcement" message and raise a dedicated, actionable error
instead (#379, #550).

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

* security: catch nested quantified groups in ReDoS guard and backslash path traversal

- hasCatastrophicBacktracking now scans across nested parens ([\s\S]*?)
  so shapes like ((a+))+ are detected; comment reframed as a heuristic
  backstop rather than a proof.
- file route path-traversal check now rejects backslash separators and a
  leading backslash, covering Windows-style "..\" payloads (CWE-22/25).

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

* chore(dev): track dev-proxy script, ignore .DS_Store and .claude/

scripts/dev-proxy.js is referenced by the "dev:ui" npm script but was
never committed, breaking the command on a fresh clone. Add it and
ignore local-only macOS/Claude Code files.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:50:55 +02:00
tdurieux 39fadd6cf0 fix: auth issue & profile save issue 2026-05-18 16:04:09 +03:00
tdurieux 9b6c8dbe62 improve admin overview 2026-05-11 12:23:24 +03:00
tdurieux afd9f36cfb improve admin overview 2026-05-11 12:10:17 +03:00
tdurieux 03e18fd572 repo change + daily stat improvements 2026-05-11 12:10:17 +03:00
tdurieux 369fd8edb2 redis cache 2026-05-07 15:55:28 +03:00
tdurieux b37a814f3a improve queue 2026-05-07 14:58:36 +03:00
tdurieux f817a29a4b loading improvements 2026-05-07 08:30:31 +03:00
tdurieux 2de08c3df3 Add missing error handlers on stream pipelines
- AnonymizedFile.anonymizedContent(): propagate content errors to the
  anonymizer so callers see the failure instead of hanging.
- AnonymizedFile.send() local path: add error handler on the anonymizer
  transform between content and response pipes.
- S3.send(): handle errors on the S3 body stream to avoid unhandled
  emits crashing the process.
- S3.archive() / FileSystem.archive(): propagate read-stream errors
  to the file transformer so archiver sees the failure.
- Add frontend translations for new error codes.
2026-05-07 07:47:29 +03:00
tdurieux fbbc694747 improve styling 2026-05-07 07:34:30 +03:00
tdurieux 9403f15ac3 Align error logging with admin dashboard field conventions
All warn/error log calls now use field names the dashboard's decorate()
function recognizes: `code` for the error code pill, `httpStatus` for the
status badge and severity bucket, `url` for the sidebar link, and
`repoId` for the repository link.

Key changes:
- Streamer errors surface code, httpStatus, url, and nested err in Raw tab
- Nested `{ err: serializeError(e) }` replaced with spread pattern so
  error fields (name, message, status) appear at the top level
- Raw Error objects in catch blocks now go through serializeError()
- Rate limit, token, and PR 404 warnings include code + httpStatus
- Dashboard stack walker traverses both `cause` and `err` chains
- Dashboard Raw tab renders repoId, filePath, upstream*, err, and cause
- trimRawArg recursively trims stacks in nested err/cause chains
- clampPayload strips heavy nested fields before falling back to
  truncated placeholder, preserving flat diagnostic fields
2026-05-07 05:54:18 +03:00
tdurieux 8fc7ac5175 Add user ban/activate feature
Add admin endpoints to ban and activate users, block banned users
from all auth flows (OAuth, token login, bearer auth), and invalidate
existing sessions on next request. Includes frontend translation and
user detail page ban/activate buttons.
2026-05-07 05:41:12 +03:00
tdurieux 48256e743c Style Ko-fi widgets to match light/dark theme
Floating button now initializes with theme-aware colors and updates
on toggle. Status page iframe uses a tuned CSS filter in dark mode
to blend with the warm palette.
2026-05-06 21:38:52 +03:00
tdurieux dfa5a2e2fd Fix repo link on admin errors page to point to repo view 2026-05-06 21:38:31 +03:00
tdurieux 1204eaffa9 Fix admin repository links and remove buttons
- Use $location.search() instead of window.location.search for URL
  params so cross-page links (owner, conference, search filters) work
  with AngularJS client-side navigation
- Add missing removeRepository() in both repos and user detail controllers
- Fix removeCache() spurious $scope.$apply() that caused digest errors
- Add confirmation prompts and list refresh after remove/cache operations
2026-05-06 21:27:57 +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 d1d6257512 fix audio url 2026-05-06 20:37:50 +03:00
tdurieux 2f6ec41a2c block indexing webpage as well 2026-05-06 20:36:04 +03:00
tdurieux bd8656206a fix persistance bugs 2026-05-06 20:00:59 +03:00
tdurieux 67cb2538b1 fix old github download repos 2026-05-06 19:37:16 +03:00