Skip to content

Initial pulumi infra#2

Open
KshitijDani wants to merge 15 commits into
RedBeardLab:llteacher01from
uw-ssec:ksdani/add-initial-pulumi-infra
Open

Initial pulumi infra#2
KshitijDani wants to merge 15 commits into
RedBeardLab:llteacher01from
uw-ssec:ksdani/add-initial-pulumi-infra

Conversation

@KshitijDani

Copy link
Copy Markdown

No description provided.

cdcore09 and others added 15 commits June 2, 2026 15:21
Phase 0 of the Django -> TypeScript migration. Stand up a two-app
monorepo (apps/web for students, apps/admin for instructors) sharing a
packages/ui design system, with /api/hello smoke test + Vitest on web.

apps/web: Vite + React 19 + Tailwind 4 + Hono on Cloudflare Workers,
Drizzle/Neon stubs, WorkOS + Vercel AI SDK scaffolds.

packages/ui: UW Husky Purple chrome + Heritage Gold AI semantics, Geist
Sans/Mono typography, 11 components, Phosphor icons, five subtle motion
moments with prefers-reduced-motion respect, collapsible sidebar with
localStorage persistence.

The Django stack (apps/{accounts,conversations,homeworks,llm}, src/,
services/) is unchanged and remains the source of truth until cutover.
Configure pixi to manage the Python environment for the Django side of
the repo. pixi.lock is marked as a binary merge / generated file in
.gitattributes so it doesn't cause noisy diffs. .gitignore also adds
*.env and /.claude/ to keep secrets and Claude Code's internal cache
out of the tree.
End-to-end loop: useChat -> /api/chat (OpenRouter + Gemma 4 31B) ->
streamed UIMessage parts -> tool-render registry -> DefinitionCard
inline. First display tool is showDefinition; more tools follow the
same pattern (server schema + UI component + registry entry).

Vite dev API proxy replaces the static /api/hello stub: loads the Hono
app via ssrLoadModule, parses .dev.vars, and streams the Response back.
Needed because @cloudflare/vite-plugin wasn't routing /api/* to the
Worker in dev. Production deploys are unaffected.

DefinitionCard styled with no card chrome - a custom SVG underline in
Heritage Gold animates in as the card's signature flourish.
New docs/architecture/ section covers the cross-cutting work shipped in
64c1be0: the end-to-end Generative UI loop (useChat -> /api/chat ->
OpenRouter -> tool-render registry -> DefinitionCard) and the Vite dev
API proxy that runs the real Hono Worker in dev for /api/* routes.

Adds DefinitionCard to the design-system component reference with full
visual + props spec, and adds a top-level docs/README.md index since the
repo has no mkdocs config.
Added in 64c1be0 to trace whether tool calls were reaching the render
registry while wiring up showDefinition end-to-end. The chat loop is now
verified working, so the diagnostic just adds console noise on every
render. Doc callout that pointed at the log is removed in the same
commit so the architecture spec doesn't reference dead code.
Builds the admin app from the placeholder shell into a navigable
instructor console with three working views and fixture data mirroring
the Django models in apps/{homeworks,llm}/src/models.py.

Aesthetic — editorial catalog console:
- Same UW Husky Purple chrome as the student web app, but the layout
  vocabulary differs: cataloged record rows with HW·xxx / CFG·xxx ID
  badges (the signature), dense tabular meta, mono small-caps status
  badges, no chat paper.
- Shared TopNav gains an `admin` prop that swaps the leading bullet of
  the affiliation tag for a Heritage Gold dot — the at-a-glance "you
  are in the instructor console" cue across the bar.
- Admin sidebar mirrors the student sidebar's collapse pattern with the
  same chevron toggle and width transition; localStorage key is
  namespaced separately (llteacher:admin-sidebar-collapsed) since the
  surface and user differ.

Views:
- HomeworksView — primary landing; stat row + record rows with
  staggered entrance animation.
- SubmissionsView — per-homework student dashboard with a small
  per-section progress grid and a filter row.
- LLMConfigsView — tutor configurations with model/temp/token meta
  and an italic quoted prompt preview.

Navigation is a type-safe tagged union in useState — no router dep
until view space outgrows it.
bd5c825 shipped the admin views, components, and styles but
apps/admin/src/client/lib/fixtures.ts was silently dropped — the
Python-style `lib/` rule near the top of .gitignore matched it, and the
existing negation only covered apps/admin/src/lib/ (a path that doesn't
exist; the admin keeps everything under client/). Without fixtures.ts
the admin won't typecheck on a fresh clone.

Adds the parallel negation for apps/admin/src/client/lib/ and commits
the missed file.
New docs/architecture/admin-console.md covers the editorial catalog
aesthetic, the view-state machine, fixture data shapes mapped 1:1 to
the Django models, the sidebar collapse pattern's two intentional
divergences from the student app, and the footguns that surfaced
during the build (the .gitignore lib/ trap chief among them).

Architecture index gains an entry pointing at the new doc, and the
TopNav reference in components.md now documents the `admin` boolean
prop with a cross-reference to admin-console.md.
Node 20 reached EOL in April 2026. Pin the engines floor to the
current Active LTS and add .nvmrc so contributors and CI track it
automatically (actions/setup-node reads .nvmrc via
node-version-file).
Establishes the data layer for the four-project shared-platform
rewrite.

Identity (schema/identity.ts): Organization, User, Course,
CourseMembership, LMSIntegration, LTILaunch, OrganizationCredential.
WorkOS as the authoritative identity ref; Canvas-projected
course/roster with partial-unique indexes guarding pending users and
non-Canvas rows.

Content (schema/content.ts): LLMConfig, PromptTemplate (polymorphic
scope via four typed FKs + num_nonnulls=1 CHECK), Homework, Section,
SectionSolution, CourseMaterial, MaterialChunk (pgvector,
1536-dim), AgentDefinition.

PII columns (email, netid, display_name) are AES-256-GCM encrypted
at rest via a Drizzle customType<Ciphertext>. Sibling HMAC-SHA256
blind-index columns support equality lookup without decryption.
IdentityCipher class is WebCrypto-only with a versioned envelope
(version byte + key id + IV + AES-GCM payload) so encryption keys
can be rotated without re-encrypting existing rows. 21 unit tests
cover round-trip correctness, IV randomness, version/key-id/tag
tampering, blind-index determinism + key separation, and
normalization edge cases.

Migrations split 0000 (identity) and 0001 (content). The pgvector
extension is captured in db/init/01_extensions.sql as the canonical
extension manifest, applied to any Postgres target (Neon dev
branch, GH Actions service, UW Neon) before drizzle migrate.
Spins up pgvector/pgvector:pg16 as a service container, applies
db/init/01_extensions.sql, runs drizzle migrations against it,
then typecheck + tests. Triggers on any PR and on pushes to
llteacher01.

Avoids the local Docker dev path entirely -- contributors use a
personal Neon project (free tier, matches prod driver and
extensions); CI is the only place the service-container pattern
runs.
Captures the entity model for the four-project shared-platform
rewrite: WorkOS identity plane + Canvas course/roster plane, the
four-level PromptTemplate hierarchy, at-rest PII encryption with
HMAC blind indexes, and the resolved/open design questions.

Includes Mermaid ER diagrams for identity (§6.1), content (§6.2),
and runtime (§6.3) entity groupings, plus a phased rollout sketch
the team can react to before code lands beyond the §6.1 + §6.2
schema scaffold.
Up arrow at the first line walks backward through prior student
messages; Down arrow at the last line walks forward and restores
the in-progress draft when past the newest entry. History is
supplied by the parent (no separate store) -- ConversationView
derives the last ten student messages directly from props.
Display tools shipped without a server-side execute, so multi-step turns
left an assistant message with an unanswered tool call — on the next user
message the model saw invalid history and emitted nothing. Add a sentinel
execute result and stopWhen: stepCountIs(5) so the model can render a
display tool and continue with follow-up text in the same turn.

Also append a synthetic pending assistant message on the client while a
request is submitted but no tokens have streamed, so the thinking dots
have something to attach to.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants