Skip to content

Handover docs plus safe fixes for known risks - #3661

Merged
bernardhanna merged 5 commits into
masterfrom
chore/handover-fixes
Sep 16, 2026
Merged

bernardhanna merged 5 commits into
masterfrom
chore/handover-fixes

Conversation

@bernardhanna

Copy link
Copy Markdown
Collaborator

Summary

  • Adds the technical handover set under docs/handover/ (architecture, Nova, bulk upload, certificates, WordPress blog, runbooks, visual tour) and redacts live SSH targets from docs/ops/learn-and-teach-resource-import.md.
  • Fixes silent Turnstile bot-protection mismatch, contact-form recipient fallback, ambassador Nova scoping, phantom app:export-search-data-to-json schedule entry, and certificate:preflight edition default.
  • Scrubs committed secrets/debris (blank APP_KEY in .env.example, cookies jar, Travis, dead /map route, unused nova-components/), runs CI on dev, and pins the bulk-upload column contract with a unit test.

Notes before merge

  • Test Turnstile on dev with a real contact-form submission; this is the one behavioural change on a public form.
  • Certificate admin gate (EnsureSuperCertificateAdmin) is intentionally unchanged — still documented as the day-one lockout in chapter 12.
  • Suite: 424 passed; 2 pre-existing failures on master unchanged (UserRestoreServiceTest, CommunityAmbassadorFilteringTest).

Test plan

  • Submit the contact form on dev.codeweek.eu and confirm Turnstile rejects a bad token / accepts a good one
  • Confirm CONTACT_FORM_RECIPIENT_EMAIL (or ADMIN_EMAIL fallback) receives the mail
  • As an ambassador in Nova, confirm Country list is scoped to their country_iso, not France
  • php artisan schedule:list — no app:export-search-data-to-json
  • php artisan certificate:preflight defaults to the current year
  • /map returns 404; /events map still works
  • CI runs on this PR (now includes dev/master PR triggers)

Made with Cursor

bernardhanna and others added 5 commits September 16, 2026 14:30
Turnstile verification never ran: the code read TURNSTILE_SECRET_KEY while
deployed environments set TURNSTILE_SECRET, so the guard was wrapped in a
truthiness check on an always-null variable and the CAPTCHA response was
validated as nullable. The widget rendered, so it looked healthy. Both names
are now accepted via config/codeweek.php, and the site key moves out of an
env() call in a Blade view so it survives config caching.

The contact form also fell back to a personal address when
CONTACT_FORM_RECIPIENT_EMAIL was unset; it now falls back to ADMIN_EMAIL.

Nova fixes:
- Country::indexQuery scoped every ambassador to 'FR' regardless of their own
  country. Uses country_iso now, and returns a query instead of null on the
  fall-through path.
- Ambassador::indexQuery matched model_has_roles.role_id = 4, which only held
  while the seeders had run in their original order. Matches by role name.

Also: certificate:preflight defaulted to --edition=2025, so a bare run
silently checked the wrong year; it now defaults to the current year. And
removed the schedule entry for app:export-search-data-to-json, a command that
does not exist anywhere in the codebase and failed nightly at 02:00.

Co-authored-by: Cursor <cursoragent@cursor.com>
.env.example shipped a real base64 APP_KEY plus live S3 bucket names, so any
environment created by copying it unchanged used a publicly known encryption
key. Those values are blanked.

It also listed QUEUE_DRIVER, the pre-Laravel-5 name the framework ignores, so
a value set only under that name had no effect. Renamed to QUEUE_CONNECTION
with a note that it must not be sync on a deployed environment.

About forty variables the application actually reads were missing entirely,
including all of mail, the MySQL connection, the OAuth secrets, the Mapbox
token, the resources bucket and PDFLATEX_PATH. Added by name with empty
values and short comments, grouped by concern.

Co-authored-by: Cursor <cursoragent@cursor.com>
Each of these currently looks like a feature and costs a reader time:

- nova-components/NovaTheme and nova-components/Analytics were never
  installed. Neither is declared as a path repository in composer.json,
  neither appears in composer.lock, and neither service provider is
  referenced outside its own directory. Analytics also had its component
  registration commented out, so it would have built an empty bundle. The
  npm build-analytics scripts that implied otherwise are removed too.
- app/Nova/Actions/PromoteAmbassador.php: handle() body was a comment, no
  fields, attached to no resource.
- app/Nova/Filters/UserStatus.php: used by nothing, hardcoded role ids.
- app/Http/Controllers/ImporterController.php: no route referenced it.
- The /map route returned a 200 with an empty <main> because
  resources/views/include/map.blade.php was a zero-byte file, and rendered
  unstyled because layout/simple.blade.php has its @Vite() calls commented
  out. Nothing linked to it. The working activity map is on /events, via
  livewire/map-wire.blade.php and components/map.blade.php, and is untouched.

Verified unreferenced before deleting; routes and the schedule still load.

Co-authored-by: Cursor <cursoragent@cursor.com>
… contract

Deleted from the repo root: texput.log, changed_files.txt, differences.diff,
bom.json, phpunit.xml.bak, tailwind.js (alongside the real
tailwind.config.js) and server.php, which Laravel 11 does not use and nothing
referenced. cookies.txt was a curl cookie jar containing a session cookie for
meet-and-code.org, captured while debugging the RSS import.

In resources/latex: nH8nokEg9c-1.tex and its .aux and .log were debris from a
failed compile. pdflatex writes personalised .tex files there at runtime, so
.aux and .log are now gitignored to stop this recurring.

Travis targeted PHP 7.3 and had no script: section; GitHub Actions is the
live pipeline. Removed .travis.yml and .env.travis.

CI ran only for master, so pull requests into dev ran no tests at all. Added
dev to both triggers.

Added a unit test pinning BulkEventUploadValidator::REQUIRED_COLUMNS. That
list is a published contract on the public wiki that national partners build
export scripts against, and nothing enforced that the two stayed in step.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fourteen chapters under docs/handover/ covering architecture, environments and
deployment, configuration, the domain model, Nova, the bulk uploaders, partner
feeds, the LaTeX certificate pipeline, the WordPress blog, the schedule and
runbooks, testing, remaining risks, and a screenshot tour mapping each screen
to the route and controller behind it. Buildable as a single PDF via
_pdf/build.py; the PDF itself is gitignored as a build artefact.

Chapter 12 is now a short list of what is genuinely open rather than an
inventory, since the preceding commits fixed most of it. It records what was
fixed so the references elsewhere still make sense.

Also redacts docs/ops/learn-and-teach-resource-import.md, which contained the
live and dev server IPs with working ssh command lines in a public repository.
Redaction does not remove them from history, so key rotation remains an open
action and is called out as such.

No credentials anywhere: environment variables are documented by name and
purpose only, with server addresses as placeholders.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bernardhanna
bernardhanna merged commit c60cc6c into master Sep 16, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant