Skip to content

Spring week notes: Chapel/PBT post, ActivityPub pulse, Vite 8#73

Closed
Jesssullivan wants to merge 11 commits into
mainfrom
week-notes-indeterminism-spring
Closed

Spring week notes: Chapel/PBT post, ActivityPub pulse, Vite 8#73
Jesssullivan wants to merge 11 commits into
mainfrom
week-notes-indeterminism-spring

Conversation

@Jesssullivan
Copy link
Copy Markdown
Owner

@Jesssullivan Jesssullivan commented Apr 27, 2026

Summary

  • Chapel/PBT host characterization post — published, with Mermaid diagrams (module graph, PBT coverage, pipeline flow, per-sample ratio + parallel time xycharts from actual capture data), skeleton compilables, and quickchpl PBT examples
  • Bigscreen DisplayID proof packet — draft post + internal doc
  • ActivityPub pulse pipeline — git pulse generator, activity stream components, mock outbox, /pulse route
  • Vite 7.3.1 → 8.0.10 migration — rolldown-vite replaced with native Vite 8

Review checklist

  • Chapel post renders correctly with Mermaid prebuild
  • No secrets or credentials in any file
  • mock-outbox.json (16K) is intentional test data, not production PII
  • Vite 8 migration doesn't break existing pages
  • ActivityPub types and fetch logic don't leak private endpoints
  • Bigscreen DisplayID post doesn't duplicate PR docs: draft Bigscreen DisplayID parser proof packet #72 scope

-Jess

Greptile Summary

This PR adds an ActivityPub-backed /pulse route (bird sightings, bike rides, code activity, sensor readings, notes), wires its prebuild data pipeline into package.json, and migrates from rolldown-vite@7.3.1 to native Vite 8. The static/data/activity-outbox.json snapshot contains no PII — all data is synthetic. Three P2 items worth addressing before enabling live fetch: NoteCard.svelte renders {@html activity.content} without sanitization (safe today with enableLiveFetch: false, XSS surface when flipped on); generate-activity-stream.mts accepts plain http:// for AP_OUTBOX_URL at build time; and generate-git-pulse.mts has a HOME || '~' fallback that silently breaks in environments where HOME is unset.

Confidence Score: 4/5

Safe to merge as-is; P2 findings should be addressed before enabling live ActivityPub fetch

All findings are P2: the XSS surface is currently gated behind a false flag, the HTTP build-time fetch is a hardening gap rather than an active exploit, and the HOME fallback only affects a manual dev script. No P0/P1 issues found.

scripts/generate-activity-stream.mts and src/lib/components/activity/NoteCard.svelte should be revisited before enableLiveFetch is set to true

Security Review

  • XSS (latent)src/lib/components/activity/NoteCard.svelte line 21: {@html activity.content} renders raw ActivityPub HTML without sanitization. Harmless while enableLiveFetch: false, but becomes an XSS vector for any visitor the moment that flag is enabled.
  • Build-time data integrityscripts/generate-activity-stream.mts: AP_OUTBOX_URL is accepted over plain http://, meaning a MITM could inject arbitrary content into the committed static/data/activity-outbox.json during CI builds.

Important Files Changed

Filename Overview
scripts/generate-activity-stream.mts Prebuild script that copies AP outbox (mock or remote) to static/data/; accepts plain http:// URLs via AP_OUTBOX_URL, which is a build-time data-integrity concern
scripts/generate-git-pulse.mts Dev-only script that reads local git history and merges code activities into mock-outbox.json; HOME fallback to literal '~' silently breaks sibling-repo scanning when HOME is unset
src/lib/components/activity/NoteCard.svelte Renders activity content via {@html} without sanitization; safe with current static data but becomes an XSS surface when enableLiveFetch is turned on
src/lib/activitypub/fetch.ts Clean fetch abstraction; live fetch guarded by enableLiveFetch flag (currently false), uses AbortSignal.timeout and falls through to empty on error
src/lib/activitypub/resolve.ts Activity resolution and summarization logic; type-safe detection of custom tl: namespaced fields; no issues found
package.json Vite 7.3.1 (rolldown-vite) → native Vite 8.0.10, @sveltejs/vite-plugin-svelte ^6→^7; generate-activity-stream.mts correctly wired into prebuild chain
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/lib/components/activity/NoteCard.svelte
Line: 21

Comment:
**`{@html}` without sanitization on live-fetch path**

`activity.content` is rendered as raw HTML. When `AP_CONFIG.enableLiveFetch` is flipped to `true`, the browser fetches from `https://tinyland.dev/@jesssullivan/outbox` at runtime and renders its `content` field here. ActivityPub `content` is freeform HTML — any XSS payload in that field would execute in every visitor's browser. Consider passing content through a sanitiser (e.g. DOMPurify) before rendering, or strip tags via the `stripHtml` helper already present in `resolve.ts` for the live-fetch code path.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: scripts/generate-activity-stream.mts
Line: 9

Comment:
**Plain `http://` URLs accepted for `AP_OUTBOX_URL`**

`fetchOutbox` branches on `source.startsWith('http')`, which permits `http://` (unencrypted) remote sources as well as `https://`. Because this script runs at **prebuild** time and its output (`static/data/activity-outbox.json`) is committed into the static site, a MITM on an `http://` endpoint could silently inject arbitrary activity data that gets shipped to visitors. Consider validating that any remote source starts with `https://`, or enforcing the check in `fetchOutbox`:

```ts
if (source.startsWith('https://')) {
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: scripts/generate-git-pulse.mts
Line: 149

Comment:
**`HOME || '~'` fallback resolves literally, not as home directory**

`resolve(process.env.HOME || '~', 'git')` — when `HOME` is unset (e.g. certain CI environments), `'~'` is treated as a literal directory name and resolves to `<cwd>/~/git`, not the actual home directory. The sibling-repo scan silently finds nothing useful rather than erroring out, which may cause confusion. Using `os.homedir()` from `node:os` is the idiomatic fix:

```ts
import { homedir } from 'node:os';
// ...
const gitDir = resolve(process.env.HOME ?? homedir(), 'git');
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "post: publish chapel/pbt host characteri..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Jesssullivan and others added 11 commits April 25, 2026 21:34
Drop the npm:rolldown-vite alias and overrides block, bump
@sveltejs/vite-plugin-svelte from v6 to v7. No config renames
needed — vite.config.ts had no rollupOptions or advancedChunks.

Build, typecheck, lint, and 88/88 unit tests pass cleanly.
Source-agnostic AP ingestion pipeline: prebuild script reads from mock
JSON now, switches to real AP outbox URL via env var when tinyland.dev
is ready. AS2-compliant schema with tl: namespace extensions for bird
sightings, bike rides, code activity, sensor readings, and freeform
notes. Five kind-specific card components with filter bar and optional
client-side live refresh. 75 mock activities spanning 90 days with
real Maine bird species, Lewiston/Auburn routes, and actual repo names.
generate-git-pulse.mts scans ~/git/ repos for commit history,
aggregates by day per repo, and merges real code activities into the
mock outbox. 410 code activities from 12,288 commits across 90 days
spanning jesssullivan.github.io, XoxdWM, cmux, scheduling-kit,
acuity-middleware, eGreg, GloriousFlywheel, rockies, linux-xr, and
aperture-bootstrap. Non-code activity types remain mock for now.
Restructured for formal methods / compiler audience:
- Leads with typed method (Chapel forall, PBT, Dhall), not RT
- Actual source snippets from HostNumaProbe.chpl, TimingProofs.chpl,
  TestTimingProofs.chpl, TestHostNumaTiming.chpl
- Nine PBT properties shown with quickchpl generators
- RT as a measured aside (~15% of post), not the centerpiece
- Passive links to linux-xr, DRM patches, Monado, quickchpl
- CSV data and raw evidence paths linked
- Module dependency graph (HostNumaProbe → TimingProofs → HostNumaTiming)
- PBT property coverage map (9 properties → 4 functions)
- Pipeline flowchart (just → Nix → chpl → capture → Dhall)
- Per-sample ratio xychart with actual data from captures
- Per-sample parallel time xychart showing RT outlier
- Skeleton compile commands (nix develop + chpl + test suite)
Updated the title and description for clarity and added more context to the content. Enhanced the explanations of tools and methodologies used in the post.
@github-actions
Copy link
Copy Markdown

📝 Blog Post Review

Found 2 blog post(s) in this PR:

Post Status Date Published Tags Linear
Bigscreen Beyond EDID Non-Desktop Handling: Evidence, Prior Art, and Submission Path 🆕 New 2026-04-25 ❌ Draft linux, kernel, drm, edid, openxr, monado, hardware, rocky-linux, bci none
Host Characterization with Chapel, Fancy Testing & Dhall ✏️ Modified 2026-04-25 ✅ Published Chapel, Nix, Dhall, NUMA, hardware, reproducibility, RT, PBT none

Schema Validation

✅ All posts pass schema validation.

Hyperlink Suggestions

  • DhallDhall (line 247)
  • NixNix (line 247)

Slash Commands

Command Description
/schedule 2026-03-15 Schedule auto-merge for a date
/publish Set all posts to published: true
/draft Set all posts back to draft
/retitle "New Title" Change a post's title
/review Re-run AI prose review
/suggest-links Find unlinked keywords


## The reproducibility pipeline
Each probe run is projected into a typed [Dhall](https://dhall-lang.org/) record via [`ChapelHostProbeRun.dhall`](https://github.com/Jesssullivan/Dell-7810/blob/main/dhall/types/ChapelHostProbeRun.dhall). The type carries metadata (date, host, compiler, kernel), configuration (locale count, channels, samples, sample rate, partitions), results (timing conforms, jitter stats), and performance (serial time, parallel time, speedup ratio). A separate [`KernelValidationRun.dhall`](https://github.com/Jesssullivan/Dell-7810/blob/main/dhall/types/KernelValidationRun.dhall) type covers kernel validation captures.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔗 Consider linking Dhall: [Dhall](https://dhall-lang.org)


## The reproducibility pipeline
Each probe run is projected into a typed [Dhall](https://dhall-lang.org/) record via [`ChapelHostProbeRun.dhall`](https://github.com/Jesssullivan/Dell-7810/blob/main/dhall/types/ChapelHostProbeRun.dhall). The type carries metadata (date, host, compiler, kernel), configuration (locale count, channels, samples, sample rate, partitions), results (timing conforms, jitter stats), and performance (serial time, parallel time, speedup ratio). A separate [`KernelValidationRun.dhall`](https://github.com/Jesssullivan/Dell-7810/blob/main/dhall/types/KernelValidationRun.dhall) type covers kernel validation captures.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔗 Consider linking Nix: [Nix](https://nixos.org)

</div>
<div class="prose prose-sm mt-1 text-surface-700-300 leading-relaxed">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html activity.content}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security {@html} without sanitization on live-fetch path

activity.content is rendered as raw HTML. When AP_CONFIG.enableLiveFetch is flipped to true, the browser fetches from https://tinyland.dev/@jesssullivan/outbox at runtime and renders its content field here. ActivityPub content is freeform HTML — any XSS payload in that field would execute in every visitor's browser. Consider passing content through a sanitiser (e.g. DOMPurify) before rendering, or strip tags via the stripHtml helper already present in resolve.ts for the live-fetch code path.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/components/activity/NoteCard.svelte
Line: 21

Comment:
**`{@html}` without sanitization on live-fetch path**

`activity.content` is rendered as raw HTML. When `AP_CONFIG.enableLiveFetch` is flipped to `true`, the browser fetches from `https://tinyland.dev/@jesssullivan/outbox` at runtime and renders its `content` field here. ActivityPub `content` is freeform HTML — any XSS payload in that field would execute in every visitor's browser. Consider passing content through a sanitiser (e.g. DOMPurify) before rendering, or strip tags via the `stripHtml` helper already present in `resolve.ts` for the live-fetch code path.

How can I resolve this? If you propose a fix, please make it concise.

*/
import { readFile, writeFile, mkdir } from 'node:fs/promises';

const OUTBOX_SOURCE = process.env.AP_OUTBOX_URL || 'scripts/data/mock-outbox.json';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security Plain http:// URLs accepted for AP_OUTBOX_URL

fetchOutbox branches on source.startsWith('http'), which permits http:// (unencrypted) remote sources as well as https://. Because this script runs at prebuild time and its output (static/data/activity-outbox.json) is committed into the static site, a MITM on an http:// endpoint could silently inject arbitrary activity data that gets shipped to visitors. Consider validating that any remote source starts with https://, or enforcing the check in fetchOutbox:

if (source.startsWith('https://')) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/generate-activity-stream.mts
Line: 9

Comment:
**Plain `http://` URLs accepted for `AP_OUTBOX_URL`**

`fetchOutbox` branches on `source.startsWith('http')`, which permits `http://` (unencrypted) remote sources as well as `https://`. Because this script runs at **prebuild** time and its output (`static/data/activity-outbox.json`) is committed into the static site, a MITM on an `http://` endpoint could silently inject arbitrary activity data that gets shipped to visitors. Consider validating that any remote source starts with `https://`, or enforcing the check in `fetchOutbox`:

```ts
if (source.startsWith('https://')) {
```

How can I resolve this? If you propose a fix, please make it concise.

}

async function main(): Promise<void> {
const gitDir = resolve(process.env.HOME || '~', 'git');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 HOME || '~' fallback resolves literally, not as home directory

resolve(process.env.HOME || '~', 'git') — when HOME is unset (e.g. certain CI environments), '~' is treated as a literal directory name and resolves to <cwd>/~/git, not the actual home directory. The sibling-repo scan silently finds nothing useful rather than erroring out, which may cause confusion. Using os.homedir() from node:os is the idiomatic fix:

import { homedir } from 'node:os';
// ...
const gitDir = resolve(process.env.HOME ?? homedir(), 'git');
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/generate-git-pulse.mts
Line: 149

Comment:
**`HOME || '~'` fallback resolves literally, not as home directory**

`resolve(process.env.HOME || '~', 'git')` — when `HOME` is unset (e.g. certain CI environments), `'~'` is treated as a literal directory name and resolves to `<cwd>/~/git`, not the actual home directory. The sibling-repo scan silently finds nothing useful rather than erroring out, which may cause confusion. Using `os.homedir()` from `node:os` is the idiomatic fix:

```ts
import { homedir } from 'node:os';
// ...
const gitDir = resolve(process.env.HOME ?? homedir(), 'git');
```

How can I resolve this? If you propose a fix, please make it concise.

@Jesssullivan
Copy link
Copy Markdown
Owner Author

Superseded by the split PRs: #74 for the Chapel/Dell publish post, #75 for the draft ActivityPub pulse work, #76 for the draft Vite 8 migration, with #72 remaining the separate draft Bigscreen proof packet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant