vault backup: 2026-04-17 17:32:48
This commit is contained in:
parent
a44ededf5d
commit
e79df7b3cc
15 changed files with 535 additions and 7 deletions
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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:** —
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
||||
<!-- New topic folders added here automatically as they are created -->
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
||||
<!-- Articles added automatically by compile.py -->
|
||||
<!-- Format: | [[concepts/slug]] | One-line summary | daily/YYYY-MM-DD.md | date | -->
|
||||
|
|
|
|||
88
wiki/concepts/fish-shell-path-config.md
Normal file
88
wiki/concepts/fish-shell-path-config.md
Normal file
|
|
@ -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
|
||||
55
wiki/concepts/librechat-openid-auth.md
Normal file
55
wiki/concepts/librechat-openid-auth.md
Normal file
|
|
@ -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`
|
||||
92
wiki/concepts/msal-vanilla-js-pkce.md
Normal file
92
wiki/concepts/msal-vanilla-js-pkce.md
Normal file
|
|
@ -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 `<script>` tag. This is appropriate for lightweight dashboards or static sites that don't use React/Next.js.
|
||||
|
||||
## Key Points
|
||||
|
||||
- MSAL v5 ships a UMD build (`msal-browser.min.js`) that works with a `<script>` tag — no npm/bundler required
|
||||
- The Azure Portal app registration **platform type must be "Single-page application"** for PKCE — if set to "Web", Azure requires a client secret and the flow will fail silently
|
||||
- PKCE flow requires no client secret — the code verifier/challenge pair handles the security
|
||||
- Backend token validation can use Node.js built-in `crypto` module + a JWKS fetch from Azure with a 24h cache — no new npm dependencies needed
|
||||
- `__SSO_ENABLED` flag in a config file allows disabling SSO without touching other files
|
||||
|
||||
## Details
|
||||
|
||||
### Script Tag Setup
|
||||
|
||||
Self-host the MSAL UMD build instead of loading from CDN to avoid external dependency:
|
||||
|
||||
```html
|
||||
<script src="/assets/msal-browser.min.js"></script>
|
||||
<script>
|
||||
const msalConfig = {
|
||||
auth: {
|
||||
clientId: CONFIG.AZURE_CLIENT_ID,
|
||||
authority: `https://login.microsoftonline.com/${CONFIG.AZURE_TENANT_ID}`,
|
||||
redirectUri: window.location.origin + "/login.html"
|
||||
},
|
||||
cache: { cacheLocation: "sessionStorage" }
|
||||
};
|
||||
const msalInstance = new window.msal.PublicClientApplication(msalConfig);
|
||||
</script>
|
||||
```
|
||||
|
||||
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
|
||||
91
wiki/concepts/shell-static-deploy-patterns.md
Normal file
91
wiki/concepts/shell-static-deploy-patterns.md
Normal file
|
|
@ -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`)
|
||||
|
|
@ -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 |
|
||||
|
||||
<!-- Articles added automatically by compile.py -->
|
||||
<!-- Format: | [[connections/slug]] | ConceptA ↔ ConceptB | daily/YYYY-MM-DD.md | date | -->
|
||||
|
|
|
|||
43
wiki/connections/oauth-state-mismatch-debugging.md
Normal file
43
wiki/connections/oauth-state-mismatch-debugging.md
Normal file
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
66
wiki/llm-models/claude-model-catalog.md
Normal file
66
wiki/llm-models/claude-model-catalog.md
Normal file
|
|
@ -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
|
||||
|
|
@ -12,3 +12,8 @@
|
|||
- KNOWLEDGE_DIR relocated from ~/.claude/memory-compiler/knowledge/ to <vault>/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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue