Commit graph

8 commits

Author SHA1 Message Date
8c8e7908fd Make logout a POST and end the Keycloak session
Clicking Logout returned 405: the base templates linked to the logout view
with a GET, which mozilla-django-oidc refuses. Both portals now post a CSRF
form instead.

A POST alone was not enough. OIDC_OP_LOGOUT_URL_METHOD is now set, so logout
builds the realm's RP-initiated end-session URL with the stored id token and
a registered post-logout redirect. Without it Keycloak kept its session and
silently signed the user back in, so the sign-in screen could never be
reached again on that browser.

Registered the post-logout redirect URIs on the ixg-platform client and
trimmed its redirect URIs to the callback on the hosts that actually serve
the platform.
2026-09-21 12:53:14 +00:00
19d67555da Add public buyer self-registration
A UK buyer can now create their own account at /portal/signup/. The screen
creates a Keycloak user through a least-privilege service account
(ixg-provisioning: manage-users, view-users) and the matching Django row as
a buyer, then sends them through the normal sign-in flow to the portal.

Staff status is derived from the role in the OIDC backend rather than
asserted, so a self-registered buyer is not staff and does not become staff
on a later sign-in. The platform root and the RBAC middleware now route
each role to its own portal, which also fixes a redirect loop that the
staff fix exposed for non-staff buyers.
2026-09-21 11:30:29 +00:00
d5bc06802e Serve map tiles from our own origin
The origin-zone map drew its background from a public tile server, which made it
the only part of the admin page that depended on a third-party domain — and the
part that breaks. Where a viewer's network, proxy or browser filter refuses
tile.openstreetmap.org (the refusal arrives as a 403) the map never draws, while
the page, the Leaflet bundle and the polygon data are all same-origin and fine.

Fetch the tiles server-side and serve them from /tiles/{z}/{x}/{y}.png: cached
on disk, so a page opened repeatedly does not re-fetch, and gated on being
signed in, so the route is not an open tile relay. The upstream stays
configurable via LEAFLET_TILE_URL, and LEAFLET_TILE_PROXY_ENABLED=False puts the
browser back on direct fetches.

When a tile still cannot be fetched, answer an empty tile rather than an error
page and say so under the map, instead of leaving a viewer with a blank grid and
no explanation.
2026-09-17 13:00:59 +00:00
5d0b5fe757 Origin zones: draw the stored polygon on a map in the admin (Leaflet 1.9.4)
Closes the "no map view" gap for origin zones: the polygon was stored as
coordinates and shown as raw JSON, so the shape could not be checked by eye.

- vendor Leaflet 1.9.4 into apps/core/static/vendor/leaflet. Self-hosted rather
  than pulled from a CDN, because this renders supplier-location data.
  PROVENANCE.md records the version, source, licence (BSD-2-Clause), checksums
  and upgrade steps; the checksums match the SRI hashes Leaflet publishes
- OriginZoneAdmin gains an "Area on a map" read-only row and its Media assets;
  apps/compliance/static/js/ixg_zone_map.js draws the polygon from the stored
  geometry, passed through a data attribute rather than injected into a script
- the tile source is a setting (LEAFLET_TILE_URL), so moving to self-hosted
  tiles is a config change, not a code change

Deliberately display only: it draws what is stored. It does not validate the
geometry, and it does not verify the zone - both remain open work, and the page
says so where the map appears.

Tests cover the drawn map, a zone with no coordinates, and the add page.
2026-09-16 16:39:07 +00:00
8f1649aaa1 Deployment hardening: HTTPS/CSRF settings, loopback-only app port, entrypoint passthrough
- settings: trust nginx X-Forwarded-Proto, mark session and CSRF cookies secure,
  and set the CSRF trusted origins for the ixgltd.com hosts
- docker-compose: bind the app port to 127.0.0.1 only; nginx fronts it, so there
  is no reason for 0.0.0.0
- entrypoint: when the container is given a command, run that instead of always
  starting gunicorn (needed for manage.py shell and the test suite)
- gitignore: keep Celery runtime state and stray local backups out of the tree

No functional change to the application itself.
2026-09-16 16:39:07 +00:00
6508cc25ef Add User Guides Viewer (Help Centre) - role-gated wiki help pages
- New apps/guides app with GuidePage model and audience mapping by wiki path
- sync_guides management command: one-way read-only sync from wikijs DB
- Read-only wikijs_ro DB role + WIKI_DB_* env config (secrets, gitignored)
- Markdown rendering with bleach sanitisation; rewrites internal guide links
  to the portal help root and wiki image paths to WIKI_PUBLIC_BASE
- /portal/help/ (buyer) and /ops/help/ (ops) index + detail views with
  role-based audience filtering (404 on cross-role guides)
- Help nav item added to both portal base templates
- Tests: audience filtering, markdown sanitisation, link rewriting, sync command
2026-08-07 14:19:49 +00:00
08096e168f P99C: compliance automation - CoA auto-generation and EUDR due diligence
- Versioned product specification table (Unrefined Shea Butter v1.0 seed) with
  spec-based QC evaluation replacing hard-coded thresholds
- Structured QC results with test methods and four-eyes verification
  (submitter cannot self-approve)
- reportlab IXG Quality Summary PDF auto-generated on quality approval,
  SHA-256 hashed; original independent lab PDF kept authoritative
- CertificateOfAnalysis version/status/hash/approval/supersede lifecycle;
  commercial release publishes to buyers and triggers notification
- EUDR evidence workflow: Facility, OriginZone, CollectorGroup, HarvestIntake,
  IntakeBatchLineage, DueDiligenceCase, EUDREvidence, RiskAssessment,
  MitigationAction, DueDiligenceStatementReference with rule-based
  completeness check and risk assessment (no AI legal conclusions)
- Ops portal: QC Approvals, CoA Reviews, EUDR Compliance screens
- Buyer portal: /portal/compliance page
- 22 automated tests covering four-eyes, CAPA, PDF+hash, publish/notify,
  EUDR blocks and buyer isolation
2026-08-05 13:58:39 +00:00
27b7fe7a13 Initial commit: IXG Platform 2026-07-29 16:48:48 +00:00