vault backup: 2026-05-05 21:04:37

This commit is contained in:
Vadym Samoilenko 2026-05-05 21:04:37 +01:00
parent 7042577196
commit acb28d9df2
8 changed files with 179 additions and 1 deletions

View file

@ -4,7 +4,7 @@
"syncFolder": "Hoarder",
"attachmentsFolder": "Hoarder/attachments",
"syncIntervalMinutes": 60,
"lastSyncTimestamp": 1778004999245,
"lastSyncTimestamp": 1778010108899,
"updateExistingFiles": false,
"excludeArchived": true,
"onlyFavorites": false,

View file

@ -210,3 +210,6 @@ tags: [daily]
- 19:50 | `aimpress`
- **Asked:** How to manage forgotten PVE server service credentials securely?
- **Done:** Populated Vaultwarden with discovered services and credentials, decrypting password hashes using Kali tools.
- 21:03 (1min) | `memory-compiler`
- **Asked:** Set up knowledge compiler for personal wiki using Karpathy's LLM schema in Obsidian.
- **Done:** Created 3 concept articles documenting iCloud duplicates, username format, and SQLite boolean patterns.

View file

@ -60,6 +60,8 @@ Same platform used by H&M. See [[wiki/client-knowledge/hm|H&M client knowledge]]
**Key quirk:** `sessionStorage` is used (not localStorage) — session is cleared on browser close. Users must log in again each browser session. This is intentional for security.
**User identity:** One2Edit usernames are email addresses in the format `FirstnameSurname@oliver.agency`. Example: Paul Johns → `PaulJohns@oliver.agency`. Look up users via `GET /api/users?clientId=<id>` — do not construct usernames by guessing. See [[wiki/concepts/one2edit-username-format|one2edit-username-format]].
---
## Related

View file

@ -0,0 +1,49 @@
---
title: "iCloud Concurrent Write: ' 2.md' Duplicate Files"
aliases: [icloud-space-2, icloud-duplicate-files]
tags: [icloud, macos, concurrency, filesystem]
sources: [memory-compiler]
created: 2026-05-05
updated: 2026-05-05
---
# iCloud Concurrent Write: ' 2.md' Duplicate Files
When two devices write to the same iCloud Drive file at the same time, iCloud resolves the conflict by keeping both versions. The second version gets a space-number suffix: `filename 2.md` (space before the number, not a hyphen or underscore).
## Key Takeaways
- Glob pattern to find duplicates: `* 2.md` (space before 2)
- Distinct from `.git` merge conflicts — this is iCloud's own conflict resolution
- Can silently accumulate: if not cleaned up, you may get `filename 2.md`, `filename 3.md`, etc.
- Most common in wiki/note systems where two machines flush to iCloud roughly simultaneously
## When It Happens
- Machine 1 is writing a file while Machine 2 is also writing the same file
- The memory-compiler multi-device workflow is a classic trigger: flush.py on Machine 2 writes the daily log; compile.py on Machine 1 also writes to wiki notes — both during the same ~21:00 window
## Detection & Cleanup
```bash
# Find all iCloud duplicate files (space-2 suffix)
find . -name "* 2.md"
# Or with glob (zsh)
ls **/*\ 2.md
```
The memory-compiler runs a LaunchAgent dedup at **09:00** and **21:30** that removes these duplicates automatically.
## Distinction from icloud-git-sync-conflict
| Scenario | File produced |
|----------|--------------|
| iCloud concurrent write (any file) | `filename 2.md` |
| git conflict in iCloud-synced repo | `filename.md` with `<<<<<<` markers |
See [[wiki/concepts/icloud-git-sync-conflict|icloud-git-sync-conflict]] for the git-specific variant.
## Related
- [[wiki/concepts/icloud-git-sync-conflict|icloud-git-sync-conflict]] — git conflict markers in iCloud-synced repos

View file

@ -0,0 +1,48 @@
---
title: "One2Edit Username Format"
aliases: [one2edit-username, one2edit-users-api]
tags: [one2edit, api, auth, 3m, hm]
sources: [01 Projects/3m-portal]
created: 2026-05-05
updated: 2026-05-05
---
# One2Edit Username Format
One2Edit usernames are **email addresses**, not `firstname.lastname` handles. This trips up anyone guessing usernames from employee names.
## Key Takeaways
- Username format: `FirstnameSurname@oliver.agency` (no dot, no hyphen)
- Example: Paul Johns → `PaulJohns@oliver.agency`
- Do NOT guess `paul.johns` or `paul.johns@oliver.agency` — these do not exist
- Use the users API to look up valid usernames, don't guess
## Users API
```
GET /api/users?clientId=<id>
```
- Requires `clientId` parameter — the request will fail or return nothing without it
- Authenticate with service account (`portal@oliver.agency`) via the CORS proxy before calling
- Returns a list of users for the given client, each with their email-format username
### Lookup Flow
```
1. Auth: POST /Api.php → externSessionId (service account)
2. Fetch: GET /api/users?clientId=<clientId> → [{username, ...}, ...]
3. Use: pass username (email) to login/session endpoints
```
## Common Mistake
> "I'll just try `paul.johns` or `p.johns@oliver.agency`"
Neither works. The canonical username is the email without dots: `PaulJohns@oliver.agency`. Always look it up from the API rather than constructing it from a name.
## Related
- [[wiki/tech-patterns/one2edit-api|one2edit-api]] — full One2Edit API integration pattern
- [[wiki/client-knowledge/3m|3m]] — 3M OMG Portal where this pattern applies

View file

@ -0,0 +1,58 @@
---
title: "SQLite: IS NOT NULL AS Boolean"
aliases: [sqlite-not-null-boolean, sqlite-derived-boolean]
tags: [sqlite, sql, security, pattern]
sources: [sandbox]
created: 2026-05-05
updated: 2026-05-05
---
# SQLite: IS NOT NULL AS Boolean
When a column contains sensitive data (e.g. a password hash), never select it directly to answer a yes/no question. Use `(column IS NOT NULL) AS flag` to return a derived boolean instead.
## Key Takeaways
- `(password_hash IS NOT NULL) AS has_password` → returns `1` or `0`, never the hash
- Hash never leaves the database layer — client gets the correct boolean
- Standard pattern for any column that must stay server-side
## Pattern
```sql
-- BAD: leaks the hash to the application layer
SELECT id, email, password_hash FROM users WHERE id = ?;
-- GOOD: returns a boolean, hash stays in DB
SELECT id, email, (password_hash IS NOT NULL) AS has_password FROM users WHERE id = ?;
```
In SQLite, the expression evaluates to `1` (true) or `0` (false). Map to a JS/Python boolean at the application layer:
```js
// Node.js / better-sqlite3
const user = db.prepare(`
SELECT id, email, (password_hash IS NOT NULL) AS has_password
FROM users WHERE id = ?
`).get(userId);
// SQLite returns 1/0; coerce to boolean
user.hasPassword = Boolean(user.has_password);
```
## Bug This Fixes
The `userPublic()` helper was selecting `u.password_hash` directly. The result object included the raw hash — or, worse, `undefined` when the column was NULL — causing `hasPassword` to always evaluate to `false` (because the hash value was truthy but the field name wasn't mapped correctly).
Fix: replace the direct column with `(password_hash IS NOT NULL) AS has_password`.
## Generalisation
The same pattern applies to any secret or large binary:
- `(api_key IS NOT NULL) AS has_api_key`
- `(avatar_blob IS NOT NULL) AS has_avatar`
- `(refresh_token IS NOT NULL) AS is_linked`
## Related
- [[wiki/concepts/fastapi-response-model-silent-field-strip|fastapi-response-model-silent-field-strip]] — similar idea: strip sensitive fields at the serialization layer

View file

@ -1,6 +1,11 @@
# Build Log
## [2026-05-05T21:00:00+01:00] compile | 2026-05-05.md (pass 2)
- Source: daily/2026-05-05.md
- Articles created: [[wiki/concepts/icloud-space-2-duplicate-files]], [[wiki/concepts/one2edit-username-format]], [[wiki/concepts/sqlite-not-null-as-boolean]]
- Articles updated: [[wiki/tech-patterns/one2edit-api]] (added Users API section + username=email gotcha); [[wiki/client-knowledge/3m]] (added One2Edit user identity note)
## [2026-05-05T23:59:00+01:00] compile | 2026-05-05.md
- Source: daily/2026-05-05.md
- Articles created: [[wiki/concepts/vite-prebuilt-subpath-workaround]], [[wiki/concepts/llamaextract-data-none-gotcha]]

View file

@ -53,7 +53,20 @@ Any client project built on the One2Edit platform (3M, H&M).
- [[01 Projects/3m-portal/3M OMG Portal|3M OMG Portal]] — Full portal: CORS proxy + Node.js backend + embedded SDK
- [[01 Projects/hm-o2e-tool/HM O2E Tool|H&M O2E Tool]] — Static tool: image relinking + document export (no proxy needed — called directly or via `python -m http.server`)
## Users API
```
GET /api/users?clientId=<id>
```
- `clientId` is **required** — the request silently fails or returns nothing without it
- Auth with service account session before calling
- Returns user list with email-format usernames
See [[wiki/concepts/one2edit-username-format|one2edit-username-format]] for full details.
## Gotchas & Lessons
- **Username format is an email address**`FirstnameSurname@oliver.agency` (e.g. `PaulJohns@oliver.agency`). Never guess `firstname.lastname` — it doesn't exist as a format
- 301/302 redirects from One2Edit mean auth failure — the Node proxy converts them to 401 to prevent redirect loops in the browser
- `sessionStorage` (not `localStorage`) — sessions clear on browser close, which is correct for this auth model
- H&M O2E tool is static (no backend) — can run without a server for most operations