diff --git a/01 Projects/ford_qc/Ford QC System.md b/01 Projects/ford_qc/Ford QC System.md index 5f3a6b5..2ea8f4c 100644 --- a/01 Projects/ford_qc/Ford QC System.md +++ b/01 Projects/ford_qc/Ford QC System.md @@ -9,8 +9,8 @@ url: server: Production server with systemd tags: [ford, qc, quality-control, box, bnp, systemd, hotfolder] created: 2026-04-14 -last_commit: 2026-04-16 -commits: 19 +last_commit: 2026-04-17 +commits: 20 --- ## Overview @@ -68,10 +68,27 @@ sudo systemctl status ford-qc-hotfolder.service ## Timeline / Git History | Date | Change | |------|--------| +| 2026-04-17 | Add asset count summary to QC HTML reports | | 2026-04-16 | Add zip filename check for GPAS naming convention | | 2026-03-16 | Make Ranger ptvl pattern configurable via profile | ## Sessions +### 2026-04-17 – Where can we find the report +**Asked:** Where can we find the report and why isn't the previously done task working? +**Done:** Generated report opened in browser using linkingrecord.json and QC results, added Asset Count card showing link and asset counts by section. + +### 2026-04-17 – Asked | Done | Log +**Asked:** Asked | Done | Log +**Done:** Feature deployment | Pushed changes and restarted dev service | ford-qc-hotfolder.service + +### 2026-04-17 – Where is the report and why +**Asked:** Where is the report and why isn't the implementation working? +**Done:** Updated implementation to display total linking records and unique assets for overall and per-section views by modifying the call site to pass four values. + +### 2026-04-17 – Asked | Where can the new +**Asked:** Asked | Where can the new report be found after implementation? | Completed +**Done:** Done | Added two new static methods before `_build_head` and verified changes | Code updated with new static methods + ### 2026-04-16 – Changed zip file naming convention from **Asked:** Changed zip file naming convention from "_image.zip" to "_GPAS.zip" for image pack validation. **Done:** Updated image pack naming format and added validation check to ensure all packs end with "_GPAS.zip" suffix. @@ -135,6 +152,10 @@ sudo systemctl status ford-qc-hotfolder.service ## Change Log | Date | Requested | Changed | Files | |------|-----------|---------|-------| +| 2026-04-17 | Report generation and deployment | Generated report with Asset Count card, linked QC results to summary | linkingrecord.json, test_reports, box-cli dev deployment | +| 2026-04-17 | Report location | Code pushed to git and deployed to box-cli dev folder | dev deployment | +| 2026-04-17 | Report display implementation | Import validation, function signature updated to accept four parameters | call site, implementation file | +| 2026-04-17 | New static methods | Added two static methods before _build_head, verified implementation | Source file | | 2026-04-16 | Image pack naming | Zip suffix changed from _image to _GPAS, validation check added | .gitignore, validation script | | 2026-04-16 | Zip naming validation | zip_filename_check implementation, validation logic, error messaging | .gitignore, validation module files | | 2026-04-16 | Zip naming update | Validation logic for _GPAS.zip suffix, .env configuration setup | .gitignore, utils/config.py, .env.example | diff --git a/99 Daily/2026-04-17.md b/99 Daily/2026-04-17.md index 44ab995..bd5c42d 100644 --- a/99 Daily/2026-04-17.md +++ b/99 Daily/2026-04-17.md @@ -347,3 +347,48 @@ tags: [daily] - 14:14 | `Barclays-banner-builder` - **Asked:** Create an idempotent deployment script for Ubuntu that builds Docker containers, pulls code, initializes database, and runs migrations. - **Done:** Analyzed project requirements and provided deployment script foundation with Docker build caching, database initialization, and migration execution strategy. +- 15:37 (2min) | `ford_qc` + - **Asked:** Asked | Where can the new report be found after implementation? | Completed + - **Done:** Done | Added two new static methods before `_build_head` and verified changes | Code updated with new static methods +- 15:40 | `ford_qc` + - **Asked:** Where is the report and why isn't the implementation working? + - **Done:** Updated implementation to display total linking records and unique assets for overall and per-section views by modifying the call site to pass four values. +- 15:41 | `ford_qc` + - **Asked:** Asked | Done | Log + - **Done:** Feature deployment | Pushed changes and restarted dev service | ford-qc-hotfolder.service +- 15:44 | `ford_qc` + - **Asked:** Where can we find the report and why isn't the previously done task working? + - **Done:** Generated report opened in browser using linkingrecord.json and QC results, added Asset Count card showing link and asset counts by section. +- 16:02 (2min) | `memory-compiler` + - **Asked:** Developer requested review of added terminal and Claude Code documentation in Obsidian wiki and identification of system improvements needed. + - **Done:** Reviewed documentation and identified additional quality checks and empty sections to refine in the system. +- 16:06 (3min) | `memory-compiler` + - **Asked:** Compile knowledge from daily conversation logs into structured wiki articles and update the master index. + - **Done:** Created 4 new concept articles documenting LibreChat OpenID auth, MSAL.js PKCE implementation, and updated the master index with new concepts and connections. +- 16:08 (1min) | `memory-compiler` + - **Asked:** Review added terminal and Claude Code documentation in Obsidian wiki and identify needed system improvements. + - **Done:** Verified compile.py pipeline, fixed bug, successfully generated 4 concept and 1 connection articles from logs. +- 16:11 | `memory-compiler` + - **Asked:** Review added wiki content about terminals and Claude Code, then identify what needs improvement in the system. + - **Done:** Fixed f-string bugs in flush.py/compile.py, merged master-index table, confirmed compile process working, and gathered configuration details. +- 16:22 | `memory-compiler` + - **Asked:** Review added terminal and Claude code content in Obsidian wiki and identify needed system improvements. + - **Done:** Reviewed Obsidian CLI documentation and identified that GitHub MCP package name was incorrect in implementation. +- 16:47 | `memory-compiler` + - **Asked:** Review the Obsidian wiki content about terminals and Claude Code, then identify what needs improvement in the system. + - **Done:** Identified conflict between forgit function aliases and custom abbreviations, and updated the cheat sheet accordingly. +- 16:52 | `memory-compiler` + - **Asked:** Review Obsidian wiki additions about terminals and Claude Code to identify missing features. + - **Done:** Documented Obsidian CLI command syntax and parameters for vault interaction. +- 17:01 (2min) | `aimpress` + - **Asked:** Asked | accomplished something + - **Done:** Audit Claude config and research top GitHub plugins for dev/design | Reviewed configuration settings and identified top-starred plugins for development and design workflows | .claude/config.json, plugin-recommendations.md +- 17:03 | `aimpress` + - **Asked:** Audit Claude Code configuration and install top-starred GitHub plugins for development and design. + - **Done:** Reviewed hooks and official plugins, then installed three official and two community plugins. +- 17:27 | `aimpress` + - **Asked:** Set up Claude Code with top-starred GitHub plugins for development and design tasks. + - **Done:** Installed three official Anthropic plugins and two community plugins with automatic context-based activation. +- 17:29 | `aimpress` + - **Asked:** Reviewed Claude configuration for development tasks | Analyzed GitHub top-starred skills and plugins for development/design, installed 5 selected tools (3 official + 2 community), confirmed session load and token usage are optimized | Configuration files, skill definitions + - **Done:** — diff --git a/wiki/_master-index.md b/wiki/_master-index.md index 7c4e946..7504c95 100644 --- a/wiki/_master-index.md +++ b/wiki/_master-index.md @@ -23,15 +23,14 @@ This 3-hop pattern works for hundreds of articles without vector search. | [[wiki/tech-patterns/_index\|tech-patterns/]] | Recurring tech stacks: FastAPI, React/Vite, Next.js, Azure AD, AI, Box, One2Edit | 9 | | [[wiki/architecture/_index\|architecture/]] | Cross-cutting architectural patterns: Docker Compose, multi-agent AI, GCP timeout, RAG, hotfolder | 5 | | [[wiki/client-knowledge/_index\|client-knowledge/]] | Per-client notes for Ford, H&M, L'Oréal (2+ projects each) | 3 | -| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 0 | -| [[wiki/connections/_index\|connections/]] | Cross-cutting insights linking 2+ concepts | 0 | +| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 4 | +| [[wiki/connections/_index\|connections/]] | Cross-cutting insights linking 2+ concepts | 1 | | [[wiki/qa/_index\|qa/]] | Filed answers to queries (saved with `--file-back`) | 0 | | [[wiki/homelab/_index\|homelab/]] | Self-hosted infra: Proxmox install, IOMMU/PCI passthrough, hypervisor setup, budget builds | 4 | | [[wiki/web-agency/_index\|web-agency/]] | AI-assisted website building & selling: Claude Code, Nanobanana 2, Kling, LaunchPath MCP | 1 | | [[wiki/dotfiles/_index\|dotfiles/]] | Linux terminal ricing: Kitty, Fish, WezTerm CLI, modern Rust CLI tools, LazyVim, unified themes, Tabby | 21 | - | [[wiki/agent-sdk/_index\|agent-sdk/]] | Claude Agent SDK (formerly Claude Code SDK) — build autonomous AI agents in Python and TypeScript | 30 | -| [[wiki/llm-models/_index\|llm-models/]] | OpenAI model catalog — GPT-5.x, o-series reasoning, audio/realtime, embeddings, moderation | 1 | +| [[wiki/llm-models/_index\|llm-models/]] | LLM model catalogs — OpenAI and Claude/Anthropic models, IDs, context, pricing | 2 | | [[wiki/claude-code/_index\|claude-code/]] | Claude Code product docs — install, capabilities, surfaces, MCP, hooks, scheduling, multi-agent, plugins, skills, channels, error recovery | 12 | diff --git a/wiki/concepts/_index.md b/wiki/concepts/_index.md index 1d4694b..72f7782 100644 --- a/wiki/concepts/_index.md +++ b/wiki/concepts/_index.md @@ -5,6 +5,10 @@ | Article | Summary | Source | Updated | |---------|---------|--------|---------| +| [[wiki/concepts/librechat-openid-auth]] | LibreChat v0.8.4 OpenID/OAuth auth internals — ALLOW_SOCIAL_REGISTRATION, openidId requirement, state mismatch diagnosis | daily/2026-04-15.md | 2026-04-15 | +| [[wiki/concepts/msal-vanilla-js-pkce]] | MSAL.js v5 UMD script-tag PKCE for SPAs without bundlers — Azure portal platform type, Node.js JWKS validation | daily/2026-04-15.md | 2026-04-15 | +| [[wiki/concepts/shell-static-deploy-patterns]] | Shell deploy scripts for static frontends — cp -r vs glob, Apache reload requirement, setup vs deploy distinction | daily/2026-04-15.md | 2026-04-15 | +| [[wiki/concepts/fish-shell-path-config]] | Fish shell PATH configuration — /usr/local/bin not in default PATH, fish_add_path, SSH aliases as Fish functions | daily/2026-04-15.md | 2026-04-15 | diff --git a/wiki/concepts/fish-shell-path-config.md b/wiki/concepts/fish-shell-path-config.md new file mode 100644 index 0000000..5447986 --- /dev/null +++ b/wiki/concepts/fish-shell-path-config.md @@ -0,0 +1,88 @@ +--- +title: "Fish Shell PATH Configuration" +aliases: [fish-path, fish-user-paths, fish_add_path, fish-env] +tags: [fish, shell, path, dotfiles, terminal] +sources: + - "daily/2026-04-15.md" +created: 2026-04-15 +updated: 2026-04-15 +--- + +# Fish Shell PATH Configuration + +Fish shell does not automatically include all standard system directories in `PATH`. Directories like `/usr/local/bin` are commonly missing, causing commands that work in bash to fail in Fish with `Unknown command`. + +## Key Points + +- `/usr/local/bin` is **not** in Fish's default PATH — tools installed there (e.g., `kubectl`, Homebrew binaries on older macOS installs) must be added explicitly +- Use `fish_add_path /usr/local/bin` to permanently add a directory — it modifies `fish_user_paths` universal variable and persists across sessions +- `set -gx fish_user_paths /usr/local/bin $fish_user_paths` is the older manual equivalent; `fish_add_path` is idempotent and preferred +- `spf --fix-config-file` (superfile config fix) requires a live TTY and cannot run from a non-interactive context like Claude Code agent +- SSH connection aliases belong in Fish functions (`~/.config/fish/functions/`) that wrap the underlying `~/.ssh/config` entries — don't duplicate host/user/key info in Fish + +## Details + +### Adding Directories to Fish PATH + +```fish +# Permanent (recommended) — idempotent, safe to run multiple times +fish_add_path /usr/local/bin +fish_add_path /opt/homebrew/bin # Apple Silicon Homebrew + +# One-time session only +set -gx PATH /usr/local/bin $PATH + +# Manual permanent (older style) +set -U fish_user_paths /usr/local/bin $fish_user_paths +``` + +`fish_add_path` checks for duplicates, so it's safe to call in `config.fish` on every startup without path bloat. + +### Diagnosing "Unknown command" Errors + +When a tool is installed but Fish can't find it: + +```fish +# Find where the binary actually lives +which kubectl # may fail +command -v kubectl + +# Check current PATH +echo $PATH + +# Find the binary manually +find /usr /opt /home -name kubectl 2>/dev/null +``` + +Once found, add the parent directory with `fish_add_path`. + +### SSH Aliases as Fish Functions + +Wrap SSH connections in named Fish functions rather than duplicating config: + +```fish +# ~/.config/fish/functions/ssh-optical.fish +function ssh-optical + ssh optical-dev # matches a Host block in ~/.ssh/config +end +``` + +`~/.ssh/config` holds the actual host, user, and identity file. The Fish function is just a convenience alias. This separation means updating the SSH config (e.g., changing a hostname) doesn't require updating Fish functions. + +### Dotfiles Context (2026-04-15 Setup) + +Terminal stack configured to match a specific video guide style: +- **Terminal:** Kitty +- **Shell:** Fish + tide prompt +- **Editor:** Neovim with kanagawa-wave theme +- **File manager:** superfile (`spf`) +- **Font:** Hasklug Nerd Font Mono, size 15 + +## Related Concepts + +- [[wiki/dotfiles/_index]] — full dotfiles topic index with Kitty, Fish, LazyVim, WezTerm articles +- [[wiki/concepts/shell-static-deploy-patterns]] — other shell scripting patterns + +## Sources + +- [[daily/2026-04-15.md]] — Fish PATH fix for `kubectl` (`/usr/local/bin` not in PATH), SSH aliases setup, terminal dotfiles configuration diff --git a/wiki/concepts/librechat-openid-auth.md b/wiki/concepts/librechat-openid-auth.md new file mode 100644 index 0000000..5a78da6 --- /dev/null +++ b/wiki/concepts/librechat-openid-auth.md @@ -0,0 +1,55 @@ +--- +title: "LibreChat OpenID / Azure AD Auth Internals" +aliases: [librechat-auth, librechat-openid, librechat-oauth] +tags: [librechat, azure-ad, oauth, openid, debugging] +sources: + - "daily/2026-04-15.md" +created: 2026-04-15 +updated: 2026-04-15 +--- + +# LibreChat OpenID / Azure AD Auth Internals + +LibreChat v0.8.4 has specific requirements for OpenID/OAuth users that are not obvious from configuration alone. The interaction between `ALLOW_SOCIAL_REGISTRATION`, MongoDB user records, and session cookies creates multiple silent failure points. + +## Key Points + +- `ALLOW_SOCIAL_REGISTRATION=false` means LibreChat checks for an existing user with `openidId` populated — a manually inserted MongoDB record without `openidId` is not recognized +- `Unknown OAuth error` in LibreChat logs means `req.session?.messages` is empty — the real error happened earlier in the session/state layer, before the verify callback +- OAuth state mismatch can occur client-side if the session cookie from a previous attempt is stale after a server restart +- The Network tab flow for a failing auth: `302 → /oauth/openid → Microsoft OK → /oauth/callback → /oauth/error` +- Always get a screenshot or Network tab capture from the user first — it identifies whether Microsoft auth succeeds before investing time in server logs + +## Details + +### ALLOW_SOCIAL_REGISTRATION and openidId + +When `ALLOW_SOCIAL_REGISTRATION=false`, LibreChat requires the user to already exist in MongoDB **with** the `openidId` field populated. Adding a user document manually (e.g., copying another user's record) does not work unless the `openidId` field contains the correct Azure AD object ID. The check order is: look up by `openidId` → if not found, registration is blocked → auth fails. + +Setting `ALLOW_SOCIAL_REGISTRATION=true` temporarily lets the user complete the flow and have `openidId` saved automatically. After the user registers, set it back to `false` and the user will be recognized on subsequent logins. + +### OAuth State Mismatch + +`Unknown OAuth error` in LibreChat server logs maps to the passport.js behavior where `req.session?.messages` is empty — this means state validation failed before the verify callback even ran. The likely causes: + +1. **Stale session cookie** — if the server restarted between when the user clicked "Login" and when Microsoft redirected back, the session store no longer has the original OAuth state. The callback `state` parameter doesn't match anything in the session → validation fails. +2. **Browser privacy settings or proxies** — if the session cookie is not sent on the callback request (third-party cookie blocking, network proxy stripping cookies), the session lookup fails silently. + +The diagnosis path: confirm Microsoft authentication *succeeds* (user sees Microsoft login page and approves) → check if redirect goes to `/oauth/callback` or directly to `/oauth/error`. If it goes to `/oauth/error`, the issue is in LibreChat's session layer, not in Azure AD. + +### Diagnosis Order + +1. Ask user for a Network tab screenshot first — identifies where the 302 chain breaks +2. Check server logs for `Unknown OAuth error` vs a specific passport error message +3. Check MongoDB for the user document and whether `openidId` is present +4. Try from a different browser / private window to rule out stale cookies + +## Related Concepts + +- [[wiki/tech-patterns/azure-ad-msal-auth]] — Azure AD app registration and PKCE configuration +- [[wiki/concepts/msal-vanilla-js-pkce]] — SPA-specific Azure AD OAuth patterns +- [[wiki/concepts/oauth-state-mismatch-debugging]] — broader OAuth state debugging patterns + +## Sources + +- [[daily/2026-04-15.md]] — LibreChat debugging session for user `santhosha.nayak@brandtech.plus` on `chat-sandbox.oliver.solutions` diff --git a/wiki/concepts/msal-vanilla-js-pkce.md b/wiki/concepts/msal-vanilla-js-pkce.md new file mode 100644 index 0000000..d6adaa3 --- /dev/null +++ b/wiki/concepts/msal-vanilla-js-pkce.md @@ -0,0 +1,92 @@ +--- +title: "MSAL.js v5 Vanilla JS PKCE (No Bundler)" +aliases: [msal-umd, msal-script-tag, msal-spa-pkce, msal-vanilla] +tags: [azure-ad, msal, pkce, spa, vanilla-js, auth] +sources: + - "daily/2026-04-15.md" +created: 2026-04-15 +updated: 2026-04-15 +--- + +# MSAL.js v5 Vanilla JS PKCE (No Bundler) + +MSAL.js v5 can be used in plain HTML/JS projects via its UMD build without a bundler. The library exposes `window.msal` from a ` + +``` + +The `window.msal` namespace is the entry point — all MSAL classes are on it. + +### Azure Portal Configuration + +The app registration platform type is critical: +- **"Single-page application"** → PKCE flow, no client secret, correct for browser-only apps +- **"Web"** → authorization code flow, expects a client secret, wrong for pure SPAs + +If the platform type is "Web", Azure will expect a client secret on the token endpoint. The PKCE flow will fail because the browser-side MSAL request doesn't send a secret. Switch to "Single-page application" in Azure Portal → Authentication → Platform configurations. + +### Backend JWKS Validation (Node.js, No Extra Deps) + +```js +// Fetch JWKS from Azure and cache for 24h +const JWKS_URL = `https://login.microsoftonline.com/${TENANT_ID}/discovery/v2.0/keys`; +let jwksCache = { keys: [], fetchedAt: 0 }; + +async function getSigningKey(kid) { + if (Date.now() - jwksCache.fetchedAt > 86400000) { + const res = await fetch(JWKS_URL); + jwksCache = { keys: (await res.json()).keys, fetchedAt: Date.now() }; + } + return jwksCache.keys.find(k => k.kid === kid); +} + +// Validate with Node.js built-in crypto +const [header64, payload64, sig64] = token.split("."); +const key = await getSigningKey(JSON.parse(atob(header64)).kid); +// ... construct public key from JWK and verify signature with crypto.verify() +``` + +This approach adds zero npm dependencies — useful in projects where keeping the dependency footprint small matters. + +### Deploy Pattern + +For this project (`social-reporting-tool`): +- `setup.sh` — first-time only: creates directories, initial container setup +- `deploy.sh` — all subsequent deploys: copies frontend files, rebuilds image +- **`deploy.sh` does NOT restart the container with updated env vars** — after adding new env vars to `.env`, manually run: `docker compose down && docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d` + +## Related Concepts + +- [[wiki/tech-patterns/azure-ad-msal-auth]] — general MSAL patterns across Oliver projects +- [[wiki/concepts/librechat-openid-auth]] — Azure AD app registration used in LibreChat context +- [[wiki/concepts/shell-static-deploy-patterns]] — deploy.sh patterns for frontend projects + +## Sources + +- [[daily/2026-04-15.md]] — MSAL v5 SSO implementation for `optical-dev.oliver.solutions` social-reporting dashboard diff --git a/wiki/concepts/shell-static-deploy-patterns.md b/wiki/concepts/shell-static-deploy-patterns.md new file mode 100644 index 0000000..c9b13b7 --- /dev/null +++ b/wiki/concepts/shell-static-deploy-patterns.md @@ -0,0 +1,91 @@ +--- +title: "Shell Deploy Script Patterns for Static Frontends" +aliases: [deploy-script, cp-recursive, frontend-deploy, apache-reload] +tags: [shell, bash, deploy, apache, nginx, static-files] +sources: + - "daily/2026-04-15.md" +created: 2026-04-15 +updated: 2026-04-15 +--- + +# Shell Deploy Script Patterns for Static Frontends + +Bash deploy scripts for static frontend projects have two common failure modes: incomplete file copying and serving stale files after deploy. Both are silent — the script exits 0 but the deployment is wrong. + +## Key Points + +- `cp frontend/*` glob does **not** recurse into subdirectories — use `cp -r frontend/. "$DEST/"` instead +- `cp -r frontend/.` (with dot) copies all contents including hidden files and nested dirs; `cp -r frontend/` copies the directory itself into the dest +- Always add `mkdir -p "$DEST"` before the copy as a safety net +- After copying static files, reload the web server: `systemctl reload apache2` (or `nginx -s reload`) — otherwise the old cached version is served +- Distinguish `setup.sh` (first-time init) from `deploy.sh` (all subsequent updates) — only `deploy.sh` runs on updates + +## Details + +### The cp Glob Pitfall + +```bash +# WRONG — skips subdirectories silently +cp frontend/* /var/www/html/ + +# CORRECT — copies all contents recursively, including hidden files +cp -r frontend/. /var/www/html/ +``` + +The shell glob `frontend/*` expands to all non-hidden entries in `frontend/` but `cp` without `-r` will skip any entries that are directories (it prints a warning but exits 0). Using `frontend/.` instead of `frontend/` as the source avoids creating a nested directory inside the destination. + +### Apache / Nginx Reload Requirement + +Web servers cache configuration and sometimes static file handles. After overwriting files in the web root: + +```bash +# Apache +systemctl reload apache2 + +# Nginx +nginx -s reload +# or +systemctl reload nginx +``` + +`reload` is preferred over `restart` — it re-reads config and gracefully hands off connections without dropping active requests. + +### Recommended deploy.sh Structure + +```bash +#!/bin/bash +set -e + +FRONTEND_DIR="/var/www/html/myapp" +BACKEND_DIR="/opt/myapp" + +# 1. Copy frontend files +mkdir -p "$FRONTEND_DIR" +cp -r frontend/. "$FRONTEND_DIR/" + +# 2. Rebuild and restart backend +cd "$BACKEND_DIR" +docker compose build +docker compose up -d + +# 3. Reload web server +systemctl reload apache2 + +echo "Deploy complete" +``` + +### setup.sh vs deploy.sh Distinction + +- `setup.sh` — runs once at first install: creates directories, sets permissions, initializes the database, sets up systemd services +- `deploy.sh` — runs on every update: copies code, rebuilds containers, reloads servers + +Never run `setup.sh` after initial setup — it may overwrite config files or re-initialize databases. + +## Related Concepts + +- [[wiki/concepts/msal-vanilla-js-pkce]] — deploy pattern for social-reporting-tool where this was encountered +- [[wiki/architecture/docker-compose-patterns]] — container restart patterns that work alongside deploy scripts + +## Sources + +- [[daily/2026-04-15.md]] — Fixed broken deploy scripts in social listening project (commit `7a70283`) diff --git a/wiki/connections/_index.md b/wiki/connections/_index.md index abf5682..0f913a7 100644 --- a/wiki/connections/_index.md +++ b/wiki/connections/_index.md @@ -5,6 +5,7 @@ | Article | Connects | Source | Updated | |---------|---------|--------|---------| +| [[wiki/connections/oauth-state-mismatch-debugging]] | LibreChat OpenID ↔ MSAL SPA ↔ Azure AD — state mismatch root cause shared across implementations | daily/2026-04-15.md | 2026-04-15 | diff --git a/wiki/connections/oauth-state-mismatch-debugging.md b/wiki/connections/oauth-state-mismatch-debugging.md new file mode 100644 index 0000000..ca81277 --- /dev/null +++ b/wiki/connections/oauth-state-mismatch-debugging.md @@ -0,0 +1,43 @@ +--- +title: "Connection: OAuth State Mismatch — LibreChat vs MSAL SPA" +connects: + - "concepts/librechat-openid-auth" + - "concepts/msal-vanilla-js-pkce" + - "tech-patterns/azure-ad-msal-auth" +sources: + - "daily/2026-04-15.md" +created: 2026-04-15 +updated: 2026-04-15 +--- + +# Connection: OAuth State Mismatch — LibreChat vs MSAL SPA + +## The Connection + +Both LibreChat's built-in OpenID integration and custom MSAL.js SPA implementations use Azure AD OAuth with state validation. OAuth state mismatch — where the `state` parameter returned by Azure doesn't match what's in the session — manifests very differently in each system but has the same root causes. + +## Key Insight + +In LibreChat, a state mismatch surfaces as `Unknown OAuth error` (the session message array is empty). In a custom MSAL.js SPA, a state mismatch surfaces as a silent redirect to an error page or a blank callback. In both cases, the fix is at the **session layer** (clear stale cookies, try a different browser), not in Azure AD configuration. This is non-obvious because the error points away from the actual cause. + +The shared root cause: if the server restarts between OAuth initiation (`/oauth/openid`) and the callback (`/oauth/callback`), the session store loses the original state. Azure sends back the correct state, but the server-side session no longer has it to compare against — the check fails. + +## Evidence + +- **LibreChat (2026-04-15):** User `santhosha.nayak@brandtech.plus` could not log in. Microsoft auth succeeded (user saw Microsoft login, approved it). LibreChat showed `Unknown OAuth error`. Network tab showed: `302 → /oauth/openid → Microsoft OK → /oauth/callback → /oauth/error`. Root cause: stale session cookie from a previous attempt after server restart. Resolution path: try different browser / clear cookies. +- **MSAL SPA (2026-04-15):** MSAL.js v5 UMD in a plain-HTML dashboard. MSAL handles state internally via `sessionStorage`. If `sessionStorage` is cleared between initiation and callback (e.g., navigation, redirect loops), MSAL throws a state mismatch error client-side. MSAL's internal handling is more transparent than LibreChat's. + +## Diagnostic Heuristic + +When OAuth fails after Microsoft auth succeeds: + +1. Check if this is a first attempt or a retry — retries are more likely to hit state mismatch +2. Check if the server recently restarted +3. Try from a different browser / incognito window +4. Only then investigate Azure AD app registration, Conditional Access, or account status + +## Related Concepts + +- [[wiki/concepts/librechat-openid-auth]] — LibreChat-specific auth internals and ALLOW_SOCIAL_REGISTRATION +- [[wiki/concepts/msal-vanilla-js-pkce]] — MSAL.js v5 UMD SPA implementation +- [[wiki/tech-patterns/azure-ad-msal-auth]] — Azure AD patterns across Oliver projects diff --git a/wiki/dotfiles/_index.md b/wiki/dotfiles/_index.md index 3182bba..5229e6c 100644 --- a/wiki/dotfiles/_index.md +++ b/wiki/dotfiles/_index.md @@ -1,3 +1,11 @@ +--- +title: "Dotfiles & Terminal Setup Index" +description: "Linux terminal customization, shell configs, CLI tool setups, and ricing guides" +tags: [index, dotfiles, terminal, wezterm, fish, cli] +created: 2026-04-15 +updated: 2026-04-17 +--- + # Dotfiles & Terminal Setup Linux terminal customization, shell configs, CLI tool setups, and ricing guides. diff --git a/wiki/llm-models/_index.md b/wiki/llm-models/_index.md index 6b4d2e1..96e28dc 100644 --- a/wiki/llm-models/_index.md +++ b/wiki/llm-models/_index.md @@ -5,3 +5,4 @@ | Article | Summary | Source | Updated | |---------|---------|--------|---------| | [[wiki/llm-models/openai-model-catalog\|OpenAI Model Catalog]] | All OpenAI API models: GPT-5.x, o-series reasoning, audio/realtime, embeddings, moderation | OpenAI API Docs | 2026-04-17 | +| [[wiki/llm-models/claude-model-catalog\|Claude Model Catalog]] | Opus/Sonnet/Haiku 4.x — IDs, context windows, when to use each, API usage, Fast Mode | Claude Code system context | 2026-04-17 | diff --git a/wiki/llm-models/claude-model-catalog.md b/wiki/llm-models/claude-model-catalog.md new file mode 100644 index 0000000..c165dfb --- /dev/null +++ b/wiki/llm-models/claude-model-catalog.md @@ -0,0 +1,66 @@ +--- +title: "Claude / Anthropic Model Catalog" +aliases: [claude-models, anthropic-models, opus-sonnet-haiku] +tags: [claude, anthropic, models, llm, ai] +sources: [knowledge cutoff Aug 2025 + Claude Code system context] +created: 2026-04-17 +updated: 2026-04-17 +--- + +## Model Families + +| Family | Tier | Best for | +|--------|------|----------| +| Opus 4.x | Most capable | Complex reasoning, architecture, long-form writing | +| Sonnet 4.x | Balanced | Coding, agentic tasks, daily work — best cost/performance | +| Haiku 4.x | Fast & cheap | Logging, classification, summaries, bulk operations | + +## Current Model IDs (Claude 4.x) + +| Model | ID | Context | Notes | +|-------|----|---------|-------| +| **Opus 4.7** | `claude-opus-4-7` | 200K | Most powerful. Fast Mode available (same model, faster output) | +| **Sonnet 4.6** | `claude-sonnet-4-6` | 200K | Default in Claude Code. Best everyday coding model | +| **Haiku 4.5** | `claude-haiku-4-5-20251001` | 200K | Use for logging/notes in Obsidian vault (per CLAUDE.md) | + +## When to Use Each Model + +**Opus** — multi-step reasoning, large refactors, security reviews, novel architecture decisions + +**Sonnet** — default for all coding tasks; Claude Code uses this; agentic pipelines, tool use, RAG + +**Haiku** — Obsidian session logging, bulk text processing, classification, any "just write text" task; cheapest + +## Claude Code Context + +- Claude Code CLI currently runs on **Sonnet 4.6** by default +- `/fast` toggles Fast Mode on Opus 4.6 (faster output, same quality) +- Memory compiler `flush.py` / `compile.py` should use Sonnet; **Obsidian logging uses Haiku** (per vault CLAUDE.md) +- Agent SDK: pass model ID in `ClaudeAgentOptions` → `model` field + +## API Usage + +```python +from anthropic import Anthropic + +client = Anthropic() +response = client.messages.create( + model="claude-sonnet-4-6", # or opus-4-7, haiku-4-5-20251001 + max_tokens=1024, + messages=[{"role": "user", "content": "Hello"}] +) +``` + +## Key Takeaways + +- Default to **Sonnet 4.6** for agentic/coding work — best balance +- Use **Haiku** for any high-volume or low-stakes generation (logging, summaries) to cut costs +- Use **Opus** only when the task genuinely requires maximum reasoning +- Model IDs include version suffix — always use full ID in code to avoid silent upgrades +- All 4.x models support 200K context window + +## Related + +- [[wiki/agent-sdk/overview|Agent SDK Overview]] — how to pass model to ClaudeAgentOptions +- [[wiki/claude-code/overview|Claude Code Overview]] — default model and Fast Mode +- [[wiki/llm-models/openai-model-catalog|OpenAI Model Catalog]] — comparison reference diff --git a/wiki/log.md b/wiki/log.md index 2ebfa11..bbd138f 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -12,3 +12,8 @@ - KNOWLEDGE_DIR relocated from ~/.claude/memory-compiler/knowledge/ to /wiki/ - All three hooks promoted to global (fire from any project directory) - Compile time set to 21:00 (9 PM) BST + +## [2026-04-17T16:03:42+01:00] compile | 2026-04-15.md +- Source: daily/2026-04-15.md +- Articles created: [[wiki/concepts/librechat-openid-auth]], [[wiki/concepts/msal-vanilla-js-pkce]], [[wiki/concepts/shell-static-deploy-patterns]], [[wiki/concepts/fish-shell-path-config]], [[wiki/connections/oauth-state-mismatch-debugging]] +- Articles updated: [[wiki/tech-patterns/azure-ad-msal-auth]] (added SPA platform type gotcha, OAuth state mismatch gotcha, daily/2026-04-15.md source) diff --git a/wiki/tech-patterns/azure-ad-msal-auth.md b/wiki/tech-patterns/azure-ad-msal-auth.md index bfad756..81ddd2d 100644 --- a/wiki/tech-patterns/azure-ad-msal-auth.md +++ b/wiki/tech-patterns/azure-ad-msal-auth.md @@ -2,7 +2,14 @@ title: "Azure AD / MSAL Authentication" aliases: [azure-ad, msal, sso, pkce] tags: [azure-ad, msal, auth, sso, pkce, security] -sources: [01 Projects/gmal-scope-builder, 01 Projects/enterprise-ai-hub-nexus, 01 Projects/cinema-studio-pro, 01 Projects/modcomms, 01 Projects/baic_dashboard, 01 Projects/sandbox-notebookllamalm-nextjs] +sources: + - "01 Projects/gmal-scope-builder" + - "01 Projects/enterprise-ai-hub-nexus" + - "01 Projects/cinema-studio-pro" + - "01 Projects/modcomms" + - "01 Projects/baic_dashboard" + - "01 Projects/sandbox-notebookllamalm-nextjs" + - "daily/2026-04-15.md" created: 2026-04-15 updated: 2026-04-15 --- @@ -76,6 +83,8 @@ instance.clearCache() - Azure App Registration must have the delegated scopes explicitly added for M365 features - `offline_access` scope required for refresh token to work (Enterprise Nexus M365) - Proactive token refresh needed for long-running Celery jobs (Enterprise Nexus SharePoint sync) +- **SPA platform type is required for PKCE** — Azure Portal → Authentication → Platform configurations must be set to "Single-page application", NOT "Web". "Web" expects a client secret; PKCE SPAs don't have one → silent auth failure (2026-04-15) +- **OAuth state mismatch** after server restart: session cookie from previous attempt doesn't match new state — always ask user to try different browser before deep-diving Azure config (2026-04-15) ## Related - [[wiki/tech-patterns/fastapi-python-docker|fastapi-python-docker]] — backend receiving tokens