Files
neuron-web/dist/vessel_stubs.c
T
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

35 lines
2.3 KiB
C

#include <stdint.h>
#include "el_runtime.h"
/* Vessel stub implementations — graceful no-ops for embodiment functions
* not linked into the soul binary. */
el_val_t avatar_speak(el_val_t text) { return EL_STR("{\"error\":\"avatar vessel not in soul binary\"}"); }
el_val_t avatar_speak_stream(el_val_t text) { return EL_STR("{\"error\":\"avatar vessel not in soul binary\"}"); }
el_val_t avatar_stream_speak(el_val_t sid, el_val_t text) { return EL_STR("{\"error\":\"avatar vessel not in soul binary\"}"); }
el_val_t avatar_stream_close(el_val_t sid) { return 0; }
el_val_t did_post_stream_sdp(el_val_t stream_id, el_val_t body) { return EL_STR("{\"error\":\"did vessel not in soul binary\"}"); }
el_val_t voice_speak(el_val_t text) { return EL_STR("{\"error\":\"voice vessel not in soul binary\"}"); }
el_val_t voice_speak_with_voice(el_val_t text, el_val_t voice_id) { return EL_STR("{\"error\":\"voice vessel not in soul binary\"}"); }
el_val_t voices_list(void) { return EL_STR("{\"error\":\"voice vessel not in soul binary\"}"); }
el_val_t camera_frame(el_val_t sid) { return EL_STR(""); }
el_val_t camera_start(el_val_t device) { return EL_STR(""); }
el_val_t camera_stop(el_val_t sid) { return 0; }
el_val_t camera_faces(el_val_t sid) { return EL_STR(""); }
el_val_t mic_start(el_val_t device) { return EL_STR(""); }
el_val_t mic_stop(el_val_t sid) { return EL_STR(""); }
el_val_t mic_segment(el_val_t sid) { return EL_STR(""); }
el_val_t stt_transcribe(el_val_t audio_b64) { return EL_STR(""); }
el_val_t jfield(el_val_t key, el_val_t value) {
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("\""), key), EL_STR("\":\"")), value), EL_STR("\""));
}
el_val_t jfield_raw(el_val_t key, el_val_t value) {
return el_str_concat(el_str_concat(el_str_concat(EL_STR("\""), key), EL_STR("\":")), value);
}
el_val_t screen_capture(void) { return EL_STR(""); }
el_val_t mouse_click(el_val_t x, el_val_t y, el_val_t button) { return 0; }
el_val_t mouse_move(el_val_t x, el_val_t y) { return 0; }
el_val_t keyboard_type(el_val_t text) { return 0; }
el_val_t keyboard_keypress(el_val_t key) { return 0; }
el_val_t browser_navigate(el_val_t url) { return 0; }
el_val_t browser_eval(el_val_t url, el_val_t js) { return EL_STR(""); }
el_val_t browser_page(void) { return EL_STR("{\"error\":\"browser vessel not in soul binary\"}"); }