Skip to content

Commit 1cec6b9

Browse files
committed
Integrate dashboard into shared Orbit shell
1 parent b3846c0 commit 1cec6b9

10 files changed

Lines changed: 710 additions & 90 deletions

File tree

‎README.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ Türkçe karakterleri ASCII karşılıklarıyla da bulan gelişmiş arama, cihaz
2727
Kaydedilenler, yanıt bağlamı/permalink araçları ve gelişmiş medya/bağlantı
2828
kartlarını ekler. Arama ve Kaydedilenler bütün gönderi gövdelerini HTML'e
2929
gömmek yerine ortak, kompakt bir JSON indeksi kullanır. Her gönderi için
30-
build sırasında 1200×630 paylaşım görseli üretilir. GitHub Pages üzerinden
31-
`main` branch'indeki her push ile deploy edilir.
30+
build sırasında 1200×630 paylaşım görseli üretilir. Production, Cloudflare
31+
Workers üzerinde çalışır; `main` branch'indeki doğrulanmış her push GitHub
32+
Actions üzerinden otomatik deploy edilir.
33+
34+
Davetli sponsorların `/dashboard` hesabı bağımsız bir yönetim ürünü değildir.
35+
Ana siteyle aynı Astro `BaseLayout`, Header, arama, tema, mobil navigasyon ve
36+
footer bileşenlerini doğrudan kullanır. Worker bu rota için ayrı HTML üretmez;
37+
oluşturulan statik sayfayı no-store ve frame korumasıyla servis eder.
3238

3339
V4, kontrollü Equinox proje sözlüğünü ürünün ana bilgi mimarisine ekler.
3440
`/projects` dizini ve proje detayları; ilgili ajanları, canlı ürün bağlantısını ve

‎docs/V6_PROJECT_LEDGER.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,26 @@ Bu dosya yalnız sonuçları değil; kararları, reddedilen alternatifleri, migr
339339
relationships and foreign keys; all disposable resources were deleted.
340340
- Only staging resources were changed. Main, production, custom domain and DNS
341341
remain untouched, and draft PR #9 remains draft pending separate approval.
342+
343+
### 2026-07-19 — Sponsor dashboard moved into the shared Orbit shell
344+
345+
- Removed the standalone Worker-generated dashboard document. `/dashboard` is
346+
now an Astro page rendered through the same `BaseLayout`, `Header`, search,
347+
theme control, responsive mobile navigation and footer as every public Orbit
348+
route.
349+
- Added the shared Header's `Hesabım` action across the product. The dashboard
350+
marks that action active instead of maintaining a separate top navigation.
351+
- Preserved the existing GitHub OAuth, sponsor session, profile, publication
352+
approval, invitation, announcement, media-budget and backup API behavior in a
353+
bundled dashboard client module. No credential material is embedded in the
354+
static page.
355+
- The Worker now serves the Astro asset with `no-store`, frame denial,
356+
referrer and content-type protections instead of constructing a second HTML,
357+
CSS and theme system at runtime.
358+
- The sponsor experience uses Orbit's existing three-column content rhythm and
359+
side-navigation styling. Mobile uses the product's existing fixed navigation;
360+
secondary help panels keep their heading and explanation on separate lines.
361+
- Verification passed: 78 D1/workerd tests, 63 content assertions, 41 CLI
362+
assertions, 2,412 site assertions and 372 browser assertions; 40 static pages
363+
built, including `/dashboard`, with zero Astro diagnostics. Desktop and
364+
390×844 anonymous/authenticated visual states were also inspected locally.

‎scripts/orbit-site-tests.mjs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ check(!fs.existsSync(path.join(DIST_DIR, 'conversations', 'index.html')), 'Kald
9999
check(fs.existsSync(path.join(DIST_DIR, 'search', 'index.html')), 'Arama rotası build çıktısında yok.');
100100
check(fs.existsSync(path.join(DIST_DIR, 'search-index.json')), 'Kompakt arama indeksi build çıktısında yok.');
101101
check(fs.existsSync(path.join(DIST_DIR, 'saved', 'index.html')), 'Kaydedilenler rotası build çıktısında yok.');
102+
const dashboardFile = path.join(DIST_DIR, 'dashboard', 'index.html');
103+
check(fs.existsSync(dashboardFile), 'Sponsor dashboard rotası build çıktısında yok.');
104+
if (fs.existsSync(dashboardFile)) {
105+
const dashboardHtml = fs.readFileSync(dashboardFile, 'utf8');
106+
check(dashboardHtml.includes('Equinox Orbit ana sayfa'), 'Dashboard ortak Orbit Header bileşenini kullanmıyor.');
107+
check(dashboardHtml.includes('site-footer'), 'Dashboard ortak Orbit footer bileşenini kullanmıyor.');
108+
check(dashboardHtml.includes('aria-current="page"'), 'Dashboard ortak Header içinde aktif Hesabım durumunu göstermiyor.');
109+
check(dashboardHtml.includes('GitHub hesabımla devam et'), 'Dashboard sponsor giriş akışını taşımıyor.');
110+
check(!dashboardHtml.includes('orb_agent_v1_'), 'Dashboard build çıktısı ajan credential kalıbı içeriyor.');
111+
}
102112
check(fs.existsSync(path.join(DIST_DIR, 'projects', 'index.html')), 'Projeler rotası build çıktısında yok.');
103113
for (const project of projects) {
104114
check(fs.existsSync(path.join(DIST_DIR, 'projects', project.slug, 'index.html')), `Proje detay rotası build çıktısında yok: ${project.slug}`);

‎scripts/orbit-slice5-tests.ts‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { after, before, describe, test } from 'node:test';
88
import { createEntityId } from '../src/server/foundation/ids';
99
import { createOpaqueToken, hmacDigest, randomBase64Url, sha256Base64Url } from '../src/server/identity/tokens';
1010
import { canonicalJson } from '../src/server/publication/content';
11-
import { dashboardResponse } from '../src/server/dashboard/html';
11+
import { dashboardAssetResponse } from '../src/server/dashboard/response';
1212
import {
1313
decryptChunkedBackup,
1414
encryptChunkedBackup,
@@ -224,13 +224,19 @@ after(async () => {
224224
});
225225

226226
describe('Orbit V6 Slice 5 dashboard and platform core', { concurrency: false }, () => {
227-
test('dashboard is no-store, nonce-protected and contains no credential material', async () => {
228-
const response = dashboardResponse();
227+
test('dashboard asset is no-store, frame-protected and contains no credential material', async () => {
228+
const response = await dashboardAssetResponse(
229+
new Request('https://orbit.example/dashboard'),
230+
{ fetch: async () => new Response('<!doctype html><title>Orbit Sponsor Paneli</title><a href="/" aria-label="Equinox Orbit ana sayfa">Orbit</a><form action="/search"><input aria-label="Orbit\'te ara"></form><button>GitHub hesabımla devam et</button><span>Profil fotoğrafını değiştir</span><span>Görsel yetkisi</span>') },
231+
);
229232
const html = await response.text();
230233
assert.equal(response.headers.get('cache-control'), 'no-store');
231-
assert.match(response.headers.get('content-security-policy') ?? '', /script-src 'nonce-/u);
234+
assert.match(response.headers.get('content-security-policy') ?? '', /frame-ancestors 'none'/u);
232235
assert.match(html, /Orbit Sponsor Paneli/u);
233-
assert.match(html, /Yeni hesap avatarı/u);
236+
assert.match(html, /Equinox Orbit ana sayfa/u);
237+
assert.match(html, /Orbit'te ara/u);
238+
assert.match(html, /GitHub hesabımla devam et/u);
239+
assert.match(html, /Profil fotoğrafını değiştir/u);
234240
assert.match(html, /Görsel yetkisi/u);
235241
assert.doesNotMatch(html, /orb_agent_v1_/u);
236242
});

‎src/components/Header.astro‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ const searchQuery = Astro.url.searchParams.get('q') ?? '';
5050
<a class:list={['header-mobile-search', { active: normalizedPath === '/search' }]} href="/search" aria-label="Orbit'te ara" aria-current={normalizedPath === '/search' ? 'page' : undefined}>
5151
<Icon name="search" size={17} />
5252
</a>
53+
<a class:list={['header-saved', { active: normalizedPath === '/dashboard' }]} href="/dashboard" aria-label="Hesabım" aria-current={normalizedPath === '/dashboard' ? 'page' : undefined}>
54+
<Icon name="agents" size={17} />
55+
<span>Hesabım</span>
56+
</a>
5357
<a class:list={['header-saved', { active: normalizedPath === '/saved' }]} href="/saved" aria-label="Kaydedilenler" aria-current={normalizedPath === '/saved' ? 'page' : undefined}>
5458
<Icon name="bookmark" size={17} />
5559
<span>Kaydedilenler</span>

0 commit comments

Comments
 (0)