- Date: 2026-05-22
- Status: Accepted
- Feature: URL-import
- Affects: url_import_spec.md § IV Phase 10, § XI.11
Context
После URL extraction pipeline нужно deliver компоненты юзеру. Изначальный draft: direct git commit + PR.
Problem: ~70% small-biz юзеров не имеют git account:
- Многие используют hosted platforms (Webflow, Squarespace, Wix)
- Технически не savvy enough setup GitHub
- Не хотят connect git до того как увидели value
Force git auth на registration → drop-off rate высокий (~40-60% по industry data для tech-tools requiring GitHub).
Это противоречит цели URL-import: lowest-friction onboarding для small-biz.
Decision
Two-tier integration strategy:
V1: Staging area (no git auth required)
Extracted компоненты сохраняются в ARNO-managed storage:
- Modal Volume (persistent storage,
$0.30/GB-mo) — для local queue - Backblaze B2 (async destination,
$0.006/GB-mo) — для long-term staging
Юзер видит компоненты в ARNO editor immediately. Connect git позже (когда хочет), then push from staging.
// V1 Phase 10
async function integrate(component) {
const arnoId = uuidv7();
const localPath = `${QUEUE_VOLUME}/${arnoId}/`;
// 1. Persistent local (Modal Volume — survives restart)
await fs.writeFiles(localPath, component.files);
// 2. Queue for async B2 upload
await queueDb.insert({ arno_id: arnoId, local_path: localPath,
target_b2_path: `staging/${user.id}/${arnoId}/` });
// 3. DB record (serving from local until uploaded)
await db.components.create({ status: 'queued', serving_from: 'local', manifest });
}
// Background worker uploads to B2 с retry
// Lazy Yjs init только на editor openV2: GitHub App + direct PR (когда product proven)
После V1 validation:
- GitHub App с installation tokens
- Direct branch creation в user repo
- PR в main для review
// V2 Phase 10
async function pushStagedToGit(userId, githubToken) {
const staged = await db.components.where({ user_id: userId, status: 'staged' });
for (const c of staged) {
const branch = `import/${sanitizeBranchName(c.name)}-${Date.now()}-${rand4}`;
await git.createBranch(user.repo, branch, githubToken);
await git.commitFiles(user.repo, branch, await b2.fetch(c.staging_path));
await git.createPR(user.repo, branch);
}
}Why staging wins для V1
- Removes registration friction — юзер тестирует ARNO перед commit к git
- 70% small-biz без git обслуживается из коробки
- Yjs editing работает immediately — не зависит от git
- V2 path не блокирован — staging compatible с future git push
Storage math
| Volume | Modal Volume local | B2 staging | Total |
|---|---|---|---|
| 100 users | $1.50/мес | $0.30 | ~$2 |
| 10k users | $15/мес | $3 | ~$18 |
| 100k users | $150/мес | $30 | ~$180 |
Acceptable — линейный scaling, predictable, в пределах $/мес уровня.
Disaster recovery (B2 outage)
Modal Volume persistent → даже если B2 down N hours, staging queue холд'ит данные:
- Worker restart → files survive (Volume persistent, не worker disk)
- B2 reconnect → async upload resumes с backoff (1m/5m/15m/1h)
-
1h queued → alert; > 24h → notify юзер "delayed sync"
Без Modal Volume: ephemeral worker disk → restart loses data → V1 broken when B2 unstable.
Lifecycle policy
Staging не вечный (см § XI.4):
- Active: < 90 days с last_activity
- Notified: 90-120 days, email "30 days до удаления"
- Deleted: 120 days physical delete
Cleanup cron weekly. Юзер ответственен за staged data.
Yjs lazy init
Yjs (Liveblocks) не initialized в Phase 10. Только когда юзер opens editor:
async function openComponentEditor(arnoId) {
let yjsDoc = await yjs.getDocument(arnoId);
if (!yjsDoc) {
const component = await loadFromStaging(arnoId);
yjsDoc = await yjs.initialize(arnoId, component);
}
return yjsDoc;
}Сохраняет cost для never-opened components (~10% юзеров skip immediately).
Consequences
Pros:
- Lower registration friction → higher conversion
- Disaster recovery от B2 outages
- 70% small-biz обслуживается без git
- V2 path preserved
Cons:
- Additional storage cost (~$2-180/мес at scales above)
- Sync state management (local vs B2 vs git)
- Юзер может lose staged components если не activate в 120 days
Alternatives rejected
A. Direct git commit на registration (исходный draft)
- ❌ 70% drop-off для small-biz
- ❌ Excludes hosted platform users entirely
B. Local-only (no B2 async)
- ❌ Worker restart loses data
- ❌ Multi-worker setup не возможен
C. Direct git OR staging (юзер выбирает)
- ❌ UX complexity на registration
- ❌ Spec complexity для two distinct paths
Cross-references
- Main spec § IV Phase 10
- Main spec § XI.11
- Main spec § XI.4 — lifecycle policy
- ADR-0006 — backend OAuth (relevant для V2 GitHub App)