posts: n8n v1→v2 migration, self-healing entitlements, TTS sidecars
Deploy / build (push) Successful in 19s

Three new posts (EN + ZH twins, og + banner each):

- n8n-v1-to-v2-upgrade-gotchas (devops): the seven deprecations that
  surfaced upgrading 1.123.x → 2.40.1, decoded from the boot log —
  telemetry schema rejection, N8N_WEBHOOK_URL rename, internal runner
  deprecation, task timeout 300s→60s, two compression limits, v3
  storage rename, plus the DB override that silently disabled the
  AI sandbox.
- self-healing-digital-goods-entitlements (case-studies): the W1–W5
  NocoDB → n8n → AList entitlement lifecycle. Build-time code sharing
  for n8n Code nodes, MAX-expiry semantics, dry-run safety, daily
  drift repair, CORS-not-HMAC reasoning, and the public→internal
  NocoDB cascading-failure fix (504 → retry storm → 503).
- running-tts-as-a-service-with-token-sidecars (ai): a year-long TTS
  service built on two cron containers that refresh Azure/Google
  tokens into a shared file, with the speed/voice mapping layer.

banner-gen: center terminal body vertically so line counts shorter
than the fixed 690px panel don't leave a dead void at the bottom.
Verified via DOM measurement (gapAbove 104 / gapBelow 106).
This commit is contained in:
2026-09-18 01:51:46 +08:00
parent be37348a8c
commit fb66e17b50
15 changed files with 1539 additions and 1 deletions
+63
View File
@@ -445,6 +445,69 @@ const BANNERS = {
],
};
BANNERS['n8n-v1-to-v2-upgrade-gotchas'] = {
titlebar: 'root@dsm — n8n v1 → v2 migration',
lines: [
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'docker pull n8nio/n8n:2.40.1 · container up in 90s' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'v1.123.x → v2.40.1 · 17 workflows · 7 active' },
{ t: 'prompt', text: 'WARN' }, { t: 'err', text: 'Telemetry failed schema validation: executions_data_save_on_error' },
{ t: 'prompt', text: 'WARN' }, { t: 'err', text: 'Failed to start Python task runner — Python 3 missing' },
{ t: 'prompt', text: 'WARN' }, { t: 'err', text: 'Sandbox: enabled=false (DB override; env was enabled=true)' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'N8N_WEBHOOK_URL · pin TASK_TIMEOUT=300 · pin compression limits' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'storage rename flagged for v3 · migrate + remount together' },
{ t: 'prompt', text: '' }, { t: 'ok', text: '→ 7 deprecations resolved · downstream workflows intact ✓' },
],
flow: [
{ n: '1', label: 'pull v2' },
{ n: '2', label: 'read boot log' },
{ n: '3', label: 'schema reject', err: true },
{ n: '4', label: 'pin defaults' },
{ n: '5', label: 'verified ✓' },
],
};
BANNERS['self-healing-digital-goods-entitlements'] = {
titlebar: 'root@dsm — entitlement lifecycle (W1W5)',
lines: [
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'nocodb webhook → n8n compute → alist role scopes' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'desired = union(active purchases, direct grants) · MAX expiry wins' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'shared/effective-grants.js inlined at build · 4 workflows' },
{ t: 'prompt', text: 'WARN' }, { t: 'err', text: 'public hostname: >60s → nginx 504 → 1s retries → pool → 503' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'http://nocodb:10380 (30ms, no tunnel) → cascade gone' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'W3 sweeps every 5min · W4 repairs drift 03:00 + verifies' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'W5 public: CORS-locked, minimal fields, no HMAC theatre' },
{ t: 'prompt', text: '' }, { t: 'ok', text: '→ repair verified · reconcile log empty when healthy ✓' },
],
flow: [
{ n: '1', label: 'grant' },
{ n: '2', label: 'expire' },
{ n: '3', label: 'drift', err: true },
{ n: '4', label: 'repair' },
{ n: '5', label: 'verify ✓' },
],
};
BANNERS['running-tts-as-a-service-with-token-sidecars'] = {
titlebar: 'root@dsm — tts service · 1 year uptime',
lines: [
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'reader → GET /webhook/{mtts,gtts}?pass=…&text=…&speed=…' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'azure speech F0 · google cloud cmn-CN-Wavenet-A' },
{ t: 'prompt', text: 'WARN' }, { t: 'err', text: 'token stored in workflow → 401 after 10min (azure) / 1h (google)' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: '2 cron sidecars → accesstoken.txt on shared volume' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'refresh 570s / 3500s · margin before expiry' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: 'map speed 550 → -20%…+150% · strip trailing newline' },
{ t: 'prompt', text: 'INFO' }, { t: 'cmd', text: '8 neural voices selected by integer index' },
{ t: 'prompt', text: '' }, { t: 'ok', text: '→ secrets in zero workflows · still running ✓' },
],
flow: [
{ n: '1', label: 'webhook' },
{ n: '2', label: 'read token' },
{ n: '3', label: 'synthesize' },
{ n: '4', label: 'audio/wav' },
{ n: '5', label: '1yr ✓' },
],
};
// ---------- read frontmatter ----------
const postPath = join(ROOT, 'src', 'content', 'posts', `${slug}.md`);
let category = 'devops';
+1 -1
View File
@@ -64,7 +64,7 @@
.terminal .dot.g { background: #3fb950; }
.terminal .title-text { margin-left: 12px; color: #6b7c99; font-size: 16px; }
.terminal .body { padding: 30px 36px; font-size: 22px; line-height: 1.8; flex: 1; }
.terminal .body { padding: 30px 36px; font-size: 22px; line-height: 1.8; flex: 1; display: flex; flex-direction: column; justify-content: center; }
.terminal .line { display: flex; gap: 12px; margin-bottom: 8px; }
.terminal .prompt { color: #7599ff; flex-shrink: 0; }
.terminal .cmd { color: #e6edf3; }
+15
View File
@@ -144,6 +144,21 @@ const TERMINALS = {
<div class="line"><span class="prompt">$</span><span class="cmd">wp plugin list · hre-ai-remix 0.0.1 → 0.0.22</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">404 …/wp-json/hre/v1<span class="hl">admin</span>/photos — rest_url() has no trailing slash</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">fix = '/admin/…' · 58 commits · 4 were the AI</span><span class="fix">→ shipped ✓</span></div>`,
'n8n-v1-to-v2-upgrade-gotchas': `
<div class="line"><span class="prompt">$</span><span class="cmd">pull n8nio/n8n:2.40.1 · restart · upgrade took 90s</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">telemetry schema: executions_data_save_on_error rejected</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">read the boot log · pin timeouts + limits</span><span class="fix">→ 7 fixed ✓</span></div>`,
'self-healing-digital-goods-entitlements': `
<div class="line"><span class="prompt">$</span><span class="cmd">nocodb → n8n W1W5 → alist role scopes</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">public hostname: 60s latency → nginx 504 → retry storm → 503</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">http://nocodb:10380 · 30ms · W4 repairs drift 03:00</span><span class="fix">→ self-healing ✓</span></div>`,
'running-tts-as-a-service-with-token-sidecars': `
<div class="line"><span class="prompt">$</span><span class="cmd">reading app → GET /webhook/mtts?pass=…&text=…</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">azure token expires in ~10min · google in ~1h</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">2 cron sidecars write accesstoken.txt · 570s / 3500s</span><span class="fix">→ 1 year uptime ✓</span></div>`,
};
const DEFAULT_TERMINAL = `