Commit Graph

7 Commits

Author SHA1 Message Date
will.anderson f2ab12e65b feat(native-el-ui): rewrite checkout/main to use el-html vessel, fix page_close linker error
- checkout.el and main.el: replace raw import of el-html vessel with direct
  extern fn declarations; implementations come from dist/elhtml_impl.c (c_source)
- Add src/elhtml.el as reference file (all el-html extern fn declarations; not imported)
- dist/elhtml_impl.c: pre-compiled el-html vessel C (strips int main + sample global)
- dist/page_close.c: pre-compiled page_close implementation; elc OOMs after emitting
  the ~71KB page_open body and silently drops page_close, so supply it as c_source
- manifest.el: add elhtml_impl.c and page_close.c as c_source entries
- .gitignore: un-ignore dist/elhtml_impl.c and dist/page_close.c
2026-05-08 22:14:38 -05:00
will.anderson 2a3f998827 fix(build): c_source stubs, manifest directives, gallery module-level global
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 13m24s
Add window/neuronCheckoutFree stubs to web_stubs.c — needed to link
without undefined symbol errors on macOS (vessel stubs were already
handled, web platform stubs were not).

Add c_source directives to manifest.el so elb includes web_stubs.c and
vessel_stubs.c in the link — requires the matching elb update in
foundation/el PR #46.

Move gallery_share_allowlist from module scope into gallery_page() to
prevent elc from emitting a second main() for the gallery module, which
caused a duplicate-symbol link error when combined with main.el.

Update elc-linux-amd64 binary (rebuilt with RBrace fix from PR #46).
2026-05-07 17:58:58 -05:00
will.anderson e6d10fc3d5 fix(demo): remove 'launch night' from opening greeting — no longer accurate
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 44s
2026-05-07 02:36:10 -05:00
will.anderson 0202b09d37 fix: rebuild soul-demo.c from source, compile against el_runtime.c directly
soul-demo.c was previously an older compiled artifact that triggered an
undefined reference to emit_metric/emit_log/trace_span_* at link time in CI.

Two fixes:
1. Rebuild soul-demo.c from soul-demo.el using current elc — cleaner
   codegen (no double-wrapped el_from_float), same logic, unix_timestamp
   collision with el_runtime.c removed.
2. Dockerfile.stage: compile soul-demo against el_runtime.c directly
   (not el_runtime.o) so all runtime symbols are always resolved from the
   staged source, bypassing any Docker layer cache divergence on el_runtime.o.
2026-05-06 21:30:25 -05:00
Will Anderson afcd03ea31 soul-demo.c: ship the history-aware Claude call source
Deploy marketing to Cloud Run / deploy (push) Failing after 51m19s
Compiled artifact for the soul-history fix that landed in prod
on tag fix-soul-history-1314. Source was built but the .c artifact
didn't get committed alongside the binary deploy. This is the
canonical compiled output of dist/soul-demo.el at HEAD; required
for clean rebuilds via Dockerfile.stage.
2026-05-02 13:21:31 -05:00
Will Anderson 46f93fd6eb security: replace denylist sanitize_share_html with allowlist el_html_sanitize
Deploy marketing to Cloud Run / deploy (push) Failing after 5s
A real attacker probed /api/share earlier today with <script>alert(1),
<iframe src=evil>, <img onerror>, <a href="javascript:...">, and a
<form action="/steal"> payload. Nothing executed because the chat
bubble at /share/<id> renders the served HTML inside marked.js's
already-escaped output, but the prior denylist sanitizer was fragile:

  - It comment-wrapped dangerous tags ("<!--script>...-->") which a
    literal "-->" inside an attacker-supplied attribute value can close
    early, re-exposing the original payload.
  - It renamed on*= attributes to data-x-on*= which left attack
    indicators visible in the served HTML.
  - It was a denylist; every new attack vector required a code change.
  - It didn't validate <a href> URL schemes properly.

The replacement is a runtime-level state-machine allowlist parser
(foundation/el af480f6: el_html_sanitize). The product just specifies
the JSON allowlist of allowed tags + attributes; the runtime drops
everything else, validates href/src URL schemes (http/https/mailto/
fragment/relative only), and drops whole subtrees of script/style/
iframe/object/embed/form regardless of the allowlist.

Phase 4 of bl-dc55ae07: deletes sanitize_share_html (main.el) and
gal_sanitize_html (gallery.el); replaces 3 call sites with
el_html_sanitize(html, allowlist). Defines default_share_allowlist
in main.el and the identical gallery_share_allowlist in gallery.el
(separate bindings to avoid a forward-reference at build-concat
order — gallery is concatenated before main).

Phase 5: migrations/20260502185500_backfill_resanitize_share_cards.sql
nulls answer_html for any share_cards row older than 1 hour. Applied
via the Supabase Management API; 0 rows in scope (the column was
added today and existing rows pre-date its first write).

Also fixes an orthogonal duplicate-symbol bug: unix_timestamp() was
defined in both dist/web_stubs.c and the runtime (the latter is a
recent runtime addition picked up by the runtime sync). Removed the
stub.

Backlog: bl-dc55ae07
2026-05-02 12:56:33 -05:00
Will Anderson 42f8602457 fix: resend email send path - http_post_auth was dropping silently
The wrapper now logs the response and returns a structured ok/error
shape. Four call sites converge on a single send_email helper.
Resend deliveries verified end to end against
will.anderson@neurontechnologies.ai (delivery IDs 492fa066, 74258223,
69a3d9ab, f6d1c889).

Root cause: http_post_auth in dist/web_stubs.c only set the
Authorization: Bearer header. Resend rejects requests without
Content-Type: application/json with HTTP 422 missing_required_field
because it parses the body as form-urlencoded. The 422 response was
being captured by the El handler but not parsed, so callers logged
the error body and returned ok-200 to the client. Two endpoints also
built malformed JSON by interpolating the raw request body unquoted
into the text field.

Fix:
- Added http_post_auth_json (Bearer + Content-Type: application/json)
  alongside http_post_auth in dist/web_stubs.c. Stripe form-POST
  callers stay on http_post_auth, JSON callers (Resend now, others
  later) move to the json variant.
- New send_email(from_addr, to, subject, html, text) wrapper in
  src/main.el. JSON-escapes all user-provided fields, parses the
  Resend response into a structured ok/error envelope, and println's
  the outcome ([email] sent id=<id>) for Cloud Run log surfaces.
- Refactored four call sites onto the wrapper: /api/enterprise-inquiry,
  /api/developer-interest, /api/waitlist, /api/attest, the family
  invite branch in /api/family/invite, and both DocuSeal completion
  branches in /api/docuseal/webhook/<token>.
- Untracked dist/ source files (web_stubs.c, vessel_stubs.c,
  soul-demo.c, entrypoint.sh, engram-snapshot.json) are now committed
  - generated artifacts (main.c, binaries) stay ignored. Without this
  the next CI rebuild would regress the fix.
2026-05-02 12:37:54 -05:00