Commit Graph

8 Commits

Author SHA1 Message Date
will.anderson 3e377e2bb6 ci: replace build-stage.sh concatenation with elb build from ci-base
- stage.yaml and deploy.yaml now extract El SDK from ci-base (docker cp /opt/el) and run elb build to produce dist/neuron-landing
- JS El sources compiled via elc --target=js in a dedicated step, matching dev.yaml exactly
- build-stage.sh replaced with thin elb wrapper for local dev use
- Removes the broken "Set up El SDK" stub (echo EL_HOME) and old build-stage.sh invocation from both workflows
2026-05-07 01:55:08 -05:00
Will Anderson 94f6e749a0 Add El source files for all client-side JS
Recovers original JS from git history and ports it into proper El source
files under src/js/. Each file wraps the original JS in a native_js call
inside a main() function, making it valid El that compiles to a
self-contained IIFE via elc --target=js --bundle.

Files added:
  src/js/account-auth.el       - Supabase OTP magic-link (sendMagicLink)
  src/js/account-dashboard.el  - Account dashboard: session, plan card, family
  src/js/chat-widget.el        - Demo chat widget (neuronDemoToggle/Send/Reset)
  src/js/checkout-auth.el      - Checkout auth: OAuth, email sign-in/up
  src/js/checkout-free.el      - Free plan: auth-badge watch -> payment reveal
  src/js/checkout-stripe.el    - Stripe Payment Element (reads NEURON_CFG)
  src/js/enterprise.el         - Enterprise inquiry form + headcount filter
  src/js/environmental.el      - Efficiency calculator slider
  src/js/gallery.el            - Gallery nav, search/sort, Supabase voting
  src/js/main.el               - Share page voting + copyForPlatform
  src/js/marketplace.el        - Developer interest form
  src/js/nav.el                - Nav hamburger + Mission dropdown
  src/js/styles.el             - Landing: nav scroll, reveal, founding counter
2026-05-04 11:23:21 -05:00
Will Anderson 254afd2fb2 fix(ci+chat): drop docker buildx flags + style chat code blocks
Deploy marketing to Cloud Run / deploy (push) Failing after 2m27s
CI: gitea runner ships docker without the buildx plugin, so
`docker buildx build --platform linux/amd64 --load` exits 125
("unknown flag: --platform") in both the full build (build-stage.sh)
and the asset-only fast path (deploy.yaml). Runner host is already
linux/amd64, so explicit --platform is redundant. Switch both call
sites to plain `docker build`. This unblocks the pipeline — every
run since the workflow was added (~26 runs) has failed at this
exact step.

Chat: the live chat bubble renders marked.parse() output via
innerHTML, but .demo-msg-ai .demo-msg-bubble only had CSS rules
for p/ul/ol/li/strong. Fenced code blocks rendered as <pre><code>
with no styling — they appeared as wrapped plaintext, hard to
distinguish from prose. Add rules for code (inline and block),
pre, blockquote, em, h1-h4, and a, mirroring the share-card
styling (which always had them) so chat code blocks finally get
the monospace + tinted-background treatment users expect.
2026-05-03 10:15:24 -05:00
Will Anderson baba6fbb71 ci: add asset-only fast path (<5min for PNG changes)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- Detect asset-only changes (src/assets/, src/shares/, static HTML, llms.txt)
  and skip El compilation, C build deps, and Docker full build entirely
- Fast path pulls :latest as base and rebuilds only the assets layer
- Gate clone-el, install-C-deps, elc-cache, build-elc, build-image, push-image
  behind asset_only != 'true'; deploy steps run unconditionally
- Switch build-stage.sh from registry cache driver (requires docker-container
  buildx driver) to inline cache backed by :latest — compatible with default
  docker driver on the runner
2026-05-02 18:08:43 -05:00
Will Anderson a185b8ae69 ci: cache elc binary + Docker layers, asset changes from 42min to ~5min
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- deploy.yaml: restore elc from GCS (gs://neuron-ci-cache) keyed on
  source SHA; only compile on cache miss, then upload for future runs
- Dockerfile.stage: pre-compile el_runtime.o as its own layer so the
  expensive object is cached when only main.c changes between runs
- build-stage.sh: add --cache-from/--cache-to pointing at Artifact
  Registry so apt-get + compilation layers survive across cold builds
2026-05-02 17:30:18 -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
Will Anderson e121038382 fix(gallery): proper auth-gated voting with persistence, undo, and change
Replaces the broken counter-bump RPC with a per-user share_votes table
(PK share_id+user_id, RLS-enforced ownership). One vote per user per
card, change direction or undo any time. Auth required for write;
read is public. share_cards.upvotes/downvotes/score stay in sync via
recalc trigger. New endpoints: POST /api/vote (auth-gated), GET
/api/vote-state/:id (auth-aware).
2026-05-02 12:14:31 -05:00
Will Anderson 640813e42e migrate stage build to native elc; chat restores from localStorage on return
Build pipeline
- build-stage.sh replaces the old in-Dockerfile bootstrap.py path. Host
  pre-compiles src/*.el into dist/main.c via the canonical native elc at
  foundation/el/dist/platform/elc and applies the stub-decl sed before
  docker buildx runs.
- Dockerfile.stage drops bootstrap.py + python3 from the builder stage
  and just runs cc on the host-supplied dist/main.c.
- Pre-rendered HTML shells under /srv/landing/ are now chowned to the
  landing user so the El page-builder's fs_write at startup can rewrite
  them — without that, post-COPY edits never reach the served HTML and
  the served page stays as the stale build-time fallback.

Chat restore
- session.verified + session.verifiedAt persist through localStorage so
  a return visit within 24h skips the Turnstile gate and lands directly
  in the restored conversation.
- restoreOrGreet() is the single source of truth for what shows up in
  the message pane after the gate clears: replays prior messages with
  skipSave, else drops the canned hello once and remembers it.
- applyVerifiedDom() hides the gate / reveals the chat row, called both
  from the verified-on-load path (DOMContentLoaded if loading, else
  immediate) and from the Turnstile callback.
- neuronDemoReset clears verified + verifiedAt so the gate returns next
  open.

Extracted JS assets (src/assets/js/*.js + manifest.json) and the
extract-js.py helper land here too — they match what the new build-stage
flow produces and removes the inline <script> blobs from the served HTML.
2026-05-02 11:15:09 -05:00