diff --git a/public/_headers b/public/_headers index b70f646..4cba835 100644 --- a/public/_headers +++ b/public/_headers @@ -1,3 +1,12 @@ +/* + Strict-Transport-Security: max-age=31536000; includeSubDomains; preload + Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com https://cdn-cgi.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://forgeos-api.synctek.io https://plausible.io; frame-ancestors 'none'; + X-Frame-Options: DENY + X-Content-Type-Options: nosniff + Referrer-Policy: strict-origin-when-cross-origin + Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=() + Cross-Origin-Opener-Policy: same-origin + /.well-known/* Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, HEAD, OPTIONS diff --git a/public/_redirects b/public/_redirects index 5d7d9e6..42d9c54 100644 --- a/public/_redirects +++ b/public/_redirects @@ -1,3 +1,4 @@ /forgeos/ /products/forgeos/ 301 /forgeos/pricing/ /products/forgeos/pricing/ 301 /forgeos/pricing /products/forgeos/pricing 301 +/pricing /products/forgeos/pricing/ 301 diff --git a/src/components/SupportWidget.astro b/src/components/SupportWidget.astro deleted file mode 100644 index 549969d..0000000 --- a/src/components/SupportWidget.astro +++ /dev/null @@ -1,25 +0,0 @@ ---- -/** - * SupportWidget — top-level wrapper for the SiteAtlas Support Chat Widget. - * - * Imported in BaseLayout.astro. Only renders when PUBLIC_SUPPORT_API_URL is set. - * Passes the configured API URL and product slug to the ChatWidget. - */ -import ChatWidget from './support/ChatWidget.astro'; - -interface Props { - productSlug?: string; -} - -const { productSlug = 'siteatlas' } = Astro.props; - -// Graceful degradation: render nothing if the API URL is not configured. -// The ChatWidget itself also handles the missing-URL case, but we short-circuit -// here to avoid shipping the widget JS/CSS to pages where support isn't wired up. -const apiUrl = import.meta.env.PUBLIC_SUPPORT_API_URL ?? ''; -const shouldRender = apiUrl.length > 0; ---- - -{shouldRender && ( - -)} diff --git a/src/components/support/ChatWidget.astro b/src/components/support/ChatWidget.astro deleted file mode 100644 index 1728e11..0000000 --- a/src/components/support/ChatWidget.astro +++ /dev/null @@ -1,761 +0,0 @@ ---- -/** - * SiteAtlas Support Chat Widget - * Vanilla JS implementation — no React dependency required. - * Connects to the SupportAtlas SSE-based API. - */ -import './ChatWidget.css'; - -interface Props { - apiUrl: string; - productSlug: string; -} - -const { apiUrl, productSlug } = Astro.props; ---- - - - - - diff --git a/src/components/support/ChatWidget.css b/src/components/support/ChatWidget.css deleted file mode 100644 index 48789e0..0000000 --- a/src/components/support/ChatWidget.css +++ /dev/null @@ -1,683 +0,0 @@ -/* ============================================================ - SiteAtlas Support Chat Widget — Styles - Dark theme with amber/gold accents matching SiteAtlas design - ============================================================ */ - -/* ----- Slide-up animation for panel ----- */ -@keyframes sw-slide-up { - from { - opacity: 0; - transform: translateY(12px) scale(0.97); - } - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} - -@keyframes sw-slide-down { - from { - opacity: 1; - transform: translateY(0) scale(1); - } - to { - opacity: 0; - transform: translateY(12px) scale(0.97); - } -} - -/* ----- Pulse for unread indicator ----- */ -@keyframes sw-pulse { - 0%, 100% { - opacity: 1; - transform: scale(1); - } - 50% { - opacity: 0.7; - transform: scale(1.2); - } -} - -/* ----- Typing dots animation ----- */ -@keyframes sw-dot-bounce { - 0%, 60%, 100% { - transform: translateY(0); - opacity: 0.4; - } - 30% { - transform: translateY(-5px); - opacity: 1; - } -} - -/* ----- Token streaming fade-in ----- */ -@keyframes sw-token-in { - from { opacity: 0; } - to { opacity: 1; } -} - -/* ----- Widget container ----- */ -#support-widget { - position: fixed; - bottom: 24px; - right: 24px; - z-index: 9999; - font-family: "Inter", ui-sans-serif, system-ui, sans-serif; - font-size: 14px; - line-height: 1.5; - color: #D4D4D4; -} - -/* ----- Floating bubble button ----- */ -#sw-bubble { - width: 56px; - height: 56px; - border-radius: 50%; - background: linear-gradient(135deg, #D97706, #F59E0B); - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 20px rgba(245, 158, 11, 0.35), 0 2px 8px rgba(0, 0, 0, 0.5); - transition: transform 0.2s ease, box-shadow 0.2s ease; - position: relative; - outline: none; -} - -#sw-bubble:hover { - transform: scale(1.08); - box-shadow: 0 6px 28px rgba(245, 158, 11, 0.45), 0 2px 10px rgba(0, 0, 0, 0.5); -} - -#sw-bubble:focus-visible { - outline: 2px solid #F59E0B; - outline-offset: 3px; -} - -#sw-bubble:active { - transform: scale(0.96); -} - -/* ----- Unread dot ----- */ -#sw-unread-dot { - position: absolute; - top: 2px; - right: 2px; - width: 12px; - height: 12px; - background: #F85149; - border-radius: 50%; - border: 2px solid #0A0A0A; - animation: sw-pulse 2s ease-in-out infinite; -} - -#sw-unread-dot.hidden { - display: none; -} - -/* ----- Chat panel ----- */ -#sw-panel { - position: absolute; - bottom: 68px; - right: 0; - width: 380px; - height: 520px; - background: #111111; - border: 1px solid #1F1F1F; - border-radius: 16px; - box-shadow: 0 25px 50px rgba(0, 0, 0, 0.7), 0 8px 20px rgba(0, 0, 0, 0.5); - display: flex; - flex-direction: column; - overflow: hidden; - animation: sw-slide-up 0.25s ease forwards; -} - -#sw-panel.sw-closing { - animation: sw-slide-down 0.2s ease forwards; -} - -#sw-panel.hidden { - display: none; -} - -/* Mobile: full-width panel */ -@media (max-width: 480px) { - #support-widget { - bottom: 16px; - right: 16px; - left: 16px; - } - - #sw-panel { - width: 100%; - right: 0; - left: 0; - height: 480px; - bottom: 68px; - } -} - -/* ----- Panel header ----- */ -#sw-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 14px 16px; - background: #0A0A0A; - border-bottom: 1px solid #1F1F1F; - flex-shrink: 0; -} - -.sw-header-title { - display: flex; - align-items: center; - gap: 8px; -} - -.sw-header-icon { - width: 28px; - height: 28px; - background: linear-gradient(135deg, #D97706, #F59E0B); - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; -} - -.sw-header-icon svg { - width: 16px; - height: 16px; - color: #0A0A0A; -} - -.sw-title-text { - display: flex; - flex-direction: column; - gap: 1px; -} - -.sw-title-name { - font-weight: 600; - font-size: 13px; - color: #E0E0E0; - letter-spacing: 0.01em; -} - -.sw-title-status { - font-size: 11px; - color: #3FB950; - display: flex; - align-items: center; - gap: 4px; -} - -.sw-status-dot { - width: 6px; - height: 6px; - background: #3FB950; - border-radius: 50%; -} - -.sw-status-dot.offline { - background: #8B949E; -} - -#sw-close-btn { - background: none; - border: none; - cursor: pointer; - color: #8B949E; - padding: 4px; - border-radius: 6px; - display: flex; - align-items: center; - justify-content: center; - transition: color 0.15s, background 0.15s; - outline: none; -} - -#sw-close-btn:hover { - color: #D4D4D4; - background: #1F1F1F; -} - -#sw-close-btn:focus-visible { - outline: 2px solid #F59E0B; - outline-offset: 2px; -} - -/* ----- Messages area ----- */ -#sw-messages { - flex: 1; - overflow-y: auto; - padding: 12px 14px; - display: flex; - flex-direction: column; - gap: 8px; - scroll-behavior: smooth; -} - -/* Custom scrollbar */ -#sw-messages::-webkit-scrollbar { - width: 4px; -} - -#sw-messages::-webkit-scrollbar-track { - background: transparent; -} - -#sw-messages::-webkit-scrollbar-thumb { - background: #2A2A2A; - border-radius: 4px; -} - -#sw-messages::-webkit-scrollbar-thumb:hover { - background: #3A3A3A; -} - -/* ----- Message bubbles ----- */ -.sw-msg { - display: flex; - flex-direction: column; - gap: 2px; - max-width: 88%; -} - -.sw-msg-user { - align-self: flex-end; - align-items: flex-end; -} - -.sw-msg-assistant { - align-self: flex-start; - align-items: flex-start; -} - -.sw-msg-system { - align-self: center; - align-items: center; - max-width: 100%; -} - -.sw-bubble-text { - padding: 8px 12px; - border-radius: 12px; - font-size: 13.5px; - line-height: 1.55; - word-break: break-word; -} - -.sw-msg-user .sw-bubble-text { - background: linear-gradient(135deg, #B45309, #D97706); - color: #FEF3C7; - border-bottom-right-radius: 3px; -} - -.sw-msg-assistant .sw-bubble-text { - background: #1A1A1A; - border: 1px solid #252525; - color: #D4D4D4; - border-bottom-left-radius: 3px; -} - -.sw-msg-system .sw-bubble-text { - background: transparent; - color: #8B949E; - font-size: 12px; - text-align: center; - border: none; - padding: 4px 0; -} - -/* Streaming cursor blink */ -.sw-streaming-cursor::after { - content: '▊'; - animation: sw-pulse 1s ease-in-out infinite; - color: #F59E0B; - font-size: 11px; - margin-left: 1px; -} - -/* ----- Timestamp ----- */ -.sw-msg-time { - font-size: 10px; - color: #4A4A4A; - padding: 0 4px; -} - -/* ----- Agent dispatch badges ----- */ -.sw-badges { - display: flex; - flex-wrap: wrap; - gap: 4px; - margin-top: 4px; - padding: 0 2px; -} - -.sw-badge { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 8px; - border-radius: 20px; - font-size: 11px; - font-weight: 500; - border: 1px solid; -} - -.sw-badge-running { - background: rgba(245, 158, 11, 0.1); - border-color: rgba(245, 158, 11, 0.3); - color: #F59E0B; -} - -.sw-badge-done { - background: rgba(63, 185, 80, 0.1); - border-color: rgba(63, 185, 80, 0.3); - color: #3FB950; -} - -.sw-badge-spinner { - width: 8px; - height: 8px; - border: 1.5px solid rgba(245, 158, 11, 0.4); - border-top-color: #F59E0B; - border-radius: 50%; - animation: spin 0.8s linear infinite; - flex-shrink: 0; -} - -@keyframes spin { - to { transform: rotate(360deg); } -} - -.sw-badge-check { - width: 8px; - height: 8px; - flex-shrink: 0; -} - -/* ----- Action cards (write approval) ----- */ -.sw-action-card { - margin-top: 6px; - padding: 10px 12px; - background: #0F0F0F; - border: 1px solid rgba(245, 158, 11, 0.25); - border-radius: 10px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.sw-action-label { - font-size: 11px; - font-weight: 600; - color: #F59E0B; - text-transform: uppercase; - letter-spacing: 0.06em; -} - -.sw-action-desc { - font-size: 12.5px; - color: #B0B0B0; - line-height: 1.4; -} - -.sw-action-buttons { - display: flex; - gap: 8px; -} - -.sw-action-btn { - padding: 5px 14px; - border-radius: 6px; - font-size: 12px; - font-weight: 500; - border: none; - cursor: pointer; - transition: opacity 0.15s, transform 0.1s; - outline: none; -} - -.sw-action-btn:active { - transform: scale(0.97); -} - -.sw-action-btn:focus-visible { - outline: 2px solid #F59E0B; - outline-offset: 2px; -} - -.sw-action-approve { - background: linear-gradient(135deg, #D97706, #F59E0B); - color: #0A0A0A; -} - -.sw-action-approve:hover { - opacity: 0.9; -} - -.sw-action-reject { - background: #1F1F1F; - color: #8B949E; - border: 1px solid #2A2A2A; -} - -.sw-action-reject:hover { - color: #D4D4D4; - background: #252525; -} - -.sw-action-approved-label { - font-size: 12px; - color: #3FB950; - display: flex; - align-items: center; - gap: 4px; -} - -/* ----- Typing indicator ----- */ -#sw-typing { - display: flex; - align-items: center; - gap: 10px; - padding: 4px 2px; - align-self: flex-start; -} - -#sw-typing.hidden { - display: none; -} - -.sw-typing-dots { - display: flex; - align-items: center; - gap: 3px; - background: #1A1A1A; - border: 1px solid #252525; - padding: 8px 12px; - border-radius: 12px; - border-bottom-left-radius: 3px; -} - -.sw-typing-dot { - width: 6px; - height: 6px; - background: #8B949E; - border-radius: 50%; - animation: sw-dot-bounce 1.2s ease-in-out infinite; -} - -.sw-typing-dot:nth-child(2) { animation-delay: 0.2s; } -.sw-typing-dot:nth-child(3) { animation-delay: 0.4s; } - -/* ----- Unavailable state ----- */ -#sw-unavailable { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 10px; - padding: 24px; - text-align: center; -} - -#sw-unavailable svg { - color: #3A3A3A; - width: 40px; - height: 40px; -} - -#sw-unavailable .sw-unavail-title { - font-weight: 600; - color: #8B949E; - font-size: 14px; -} - -#sw-unavailable .sw-unavail-sub { - font-size: 12px; - color: #4A4A4A; - line-height: 1.5; -} - -/* ----- Empty state ----- */ -#sw-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 10px; - padding: 24px; - text-align: center; -} - -.sw-empty-icon { - width: 48px; - height: 48px; - background: linear-gradient(135deg, rgba(217, 119, 6, 0.15), rgba(245, 158, 11, 0.1)); - border: 1px solid rgba(245, 158, 11, 0.2); - border-radius: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.sw-empty-icon svg { - color: #F59E0B; - width: 24px; - height: 24px; -} - -.sw-empty-title { - font-weight: 600; - font-size: 14px; - color: #D4D4D4; -} - -.sw-empty-sub { - font-size: 12px; - color: #8B949E; - line-height: 1.5; - max-width: 240px; -} - -/* ----- Input area ----- */ -#sw-input-area { - display: flex; - align-items: flex-end; - gap: 8px; - padding: 12px 14px; - border-top: 1px solid #1F1F1F; - background: #0A0A0A; - flex-shrink: 0; -} - -#sw-input { - flex: 1; - background: #1A1A1A; - border: 1px solid #2A2A2A; - border-radius: 10px; - padding: 8px 12px; - color: #D4D4D4; - font-family: inherit; - font-size: 13.5px; - line-height: 1.5; - resize: none; - min-height: 36px; - max-height: 100px; - outline: none; - transition: border-color 0.15s; - overflow-y: auto; -} - -#sw-input::placeholder { - color: #4A4A4A; -} - -#sw-input:focus { - border-color: rgba(245, 158, 11, 0.4); -} - -#sw-input::-webkit-scrollbar { - width: 3px; -} - -#sw-input::-webkit-scrollbar-thumb { - background: #2A2A2A; - border-radius: 3px; -} - -#sw-send-btn { - width: 36px; - height: 36px; - flex-shrink: 0; - background: linear-gradient(135deg, #D97706, #F59E0B); - border: none; - border-radius: 8px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: opacity 0.15s, transform 0.1s; - outline: none; -} - -#sw-send-btn:hover:not(:disabled) { - opacity: 0.9; -} - -#sw-send-btn:active:not(:disabled) { - transform: scale(0.93); -} - -#sw-send-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -#sw-send-btn:focus-visible { - outline: 2px solid #F59E0B; - outline-offset: 2px; -} - -#sw-send-btn svg { - width: 16px; - height: 16px; - color: #0A0A0A; -} - -/* ----- Error toast ----- */ -.sw-error-toast { - padding: 8px 12px; - background: rgba(248, 81, 73, 0.12); - border: 1px solid rgba(248, 81, 73, 0.3); - border-radius: 8px; - color: #F85149; - font-size: 12px; - align-self: center; - max-width: 100%; - text-align: center; -} diff --git a/src/components/support/types.ts b/src/components/support/types.ts deleted file mode 100644 index f958816..0000000 --- a/src/components/support/types.ts +++ /dev/null @@ -1,93 +0,0 @@ -// SSE event types from SupportAtlas API - -export type SSEEventType = - | 'token' - | 'tool_start' - | 'tool_end' - | 'action_card' - | 'done' - | 'error'; - -export interface TokenEvent { - type: 'token'; - content: string; -} - -export interface ToolStartEvent { - type: 'tool_start'; - agentName: string; - toolName: string; - input: Record; -} - -export interface ToolEndEvent { - type: 'tool_end'; - result: Record; -} - -export interface ActionCardEvent { - type: 'action_card'; - actionId: string; - description: string; - payload: Record; -} - -export interface DoneEvent { - type: 'done'; -} - -export interface ErrorEvent { - type: 'error'; - message: string; -} - -export type SSEEvent = - | TokenEvent - | ToolStartEvent - | ToolEndEvent - | ActionCardEvent - | DoneEvent - | ErrorEvent; - -// Message types for chat history - -export type MessageRole = 'user' | 'assistant' | 'system'; - -export interface AgentBadge { - agentName: string; - toolName: string; - status: 'running' | 'done'; -} - -export interface ActionCard { - actionId: string; - description: string; - payload: Record; - approved?: boolean; -} - -export interface ChatMessage { - id: string; - role: MessageRole; - content: string; - timestamp: number; - streaming?: boolean; - agentBadges?: AgentBadge[]; - actionCards?: ActionCard[]; -} - -// Session persistence - -export interface ChatSession { - sessionId: string; - messages: ChatMessage[]; - createdAt: number; - lastActiveAt: number; -} - -// Widget config - -export interface WidgetConfig { - apiUrl: string; - productSlug: string; -} diff --git a/src/content/blog/2026-03-06-we-ran-25-packages-through-3-scoring-tools.mdx b/src/content/blog/2026-03-06-we-ran-25-packages-through-3-scoring-tools.mdx index 3813037..a2186f1 100644 --- a/src/content/blog/2026-03-06-we-ran-25-packages-through-3-scoring-tools.mdx +++ b/src/content/blog/2026-03-06-we-ran-25-packages-through-3-scoring-tools.mdx @@ -148,7 +148,7 @@ We are publishing this data because cross-tool comparison should be normal, not ## Raw Data -The full dataset, including per-dimension breakdowns and correlation analysis, is available in the [FTI baseline repository](https://github.com/SyncTek-LLC/forgeos/tree/main/scripts/fti-baseline/data). +The full dataset, including per-dimension breakdowns and correlation analysis, is available upon request — contact [support@synctek.io](mailto:support@synctek.io). Files included: - `summary_table.csv` - All 25 packages with three-tool scores diff --git a/src/content/blog/getting-started-forgeos-5-minutes.mdx b/src/content/blog/getting-started-forgeos-5-minutes.mdx index 5c0a35a..b905414 100644 --- a/src/content/blog/getting-started-forgeos-5-minutes.mdx +++ b/src/content/blog/getting-started-forgeos-5-minutes.mdx @@ -157,7 +157,7 @@ A few places to go from here: **Dashboard:** [forgeos.synctek.io](https://forgeos.synctek.io) — visualize your initiative pipeline, inspect the ledger, manage your team's projects and API keys. -**API docs:** [forgeos-api.synctek.io](https://forgeos-api.synctek.io) — 135+ endpoints if you want to build governance into your own tooling or scripts. +**API docs:** [forgeos-api.synctek.io](https://forgeos-api.synctek.io) — 239 endpoints if you want to build governance into your own tooling or scripts. **FTI trust score:** ForgeOS computes a ForgeOS Trust Index score across eight dimensions: security, maintainability, documentation, community health, supply chain, improvement velocity, governance, and operational. Check your project's score in the dashboard under the Trust tab. diff --git a/src/content/blog/ship-first-governed-project-5-minutes.mdx b/src/content/blog/ship-first-governed-project-5-minutes.mdx index 77b8fc9..d14a00d 100644 --- a/src/content/blog/ship-first-governed-project-5-minutes.mdx +++ b/src/content/blog/ship-first-governed-project-5-minutes.mdx @@ -221,7 +221,7 @@ That answer took five minutes to set up. It will pay back for the entire lifecyc **Where to go next:** - **Dashboard:** [forgeos.synctek.io](https://forgeos.synctek.io) — visualize your initiative pipeline, inspect the ledger, manage team projects and API keys -- **API docs:** [forgeos-api.synctek.io](https://forgeos-api.synctek.io) — 135+ endpoints for building governance into your own tooling +- **API docs:** [forgeos-api.synctek.io](https://forgeos-api.synctek.io) — 239 endpoints for building governance into your own tooling - **FTI trust score:** Check your project's trust score under the Trust tab in the dashboard [Start the 14-day trial →](/forgeos) diff --git a/src/content/legal/privacy.md b/src/content/legal/privacy.md index 7a2b9d0..2300e60 100644 --- a/src/content/legal/privacy.md +++ b/src/content/legal/privacy.md @@ -483,7 +483,7 @@ You have the following rights with respect to your personal data: We have designated a data protection contact for GDPR purposes: **Data Protection Contact:** info@synctek.io -**Postal Address:** SyncTek LLC, [Registered Address] +**Postal Address:** SyncTek LLC, 5540 Centerview Dr Ste 204 #462485, Raleigh, NC 27606 ### Right to Lodge a Complaint diff --git a/src/data/forgeos.json b/src/data/forgeos.json index 325b245..97365c6 100644 --- a/src/data/forgeos.json +++ b/src/data/forgeos.json @@ -14,7 +14,6 @@ "api": "https://forgeos-api.synctek.io", "docs": "https://forgeos.synctek.io/docs", "support": "support@synctek.io", - "github": "https://github.com/SyncTek-LLC/forgeos", "npm": "https://www.npmjs.com/package/@synctek/forgeos", "federation": "https://federation.synctek.io" }, @@ -247,7 +246,7 @@ "capabilities": { "cli_commands": 49, "mcp_tools": 21, - "api_endpoints": 135, + "api_endpoints": 239, "gate_types": 16, "supported_languages": [ "Python", diff --git a/src/data/fti.json b/src/data/fti.json index d1be155..3dfa997 100644 --- a/src/data/fti.json +++ b/src/data/fti.json @@ -3,7 +3,7 @@ "name": "ForgeOS Trust Index", "tagline": "We don't have a #1. We have your #1.", "description_short": "Context-aware trust scoring for open-source packages. Scores tailored to your security posture, team size, and tech stack.", - "description_long": "The ForgeOS Trust Index (FTI) evaluates open-source packages across\n6 scoring dimensions — security, maintenance, community health,\ncode quality, documentation, and licensing. Unlike static rankings,\nFTI provides context-aware recommendations based on YOUR specific\nneeds: security posture, team size, preferred language, and runtime.\n\nFTI is the first trust infrastructure that answers \"is this package\nright for ME?\" instead of \"is this package popular?\"\n", + "description_long": "The ForgeOS Trust Index (FTI) evaluates open-source packages across\n8 scoring dimensions — security, maintainability, documentation,\ncommunity health, supply chain, improvement velocity, governance,\nand operational. Unlike static rankings,\nFTI provides context-aware recommendations based on YOUR specific\nneeds: security posture, team size, preferred language, and runtime.\n\nFTI is the first trust infrastructure that answers \"is this package\nright for ME?\" instead of \"is this package popular?\"\n", "brand": { "accent_color": "#4f46e5", "design_language": "Measured Authority" @@ -102,32 +102,50 @@ { "id": "security", "name": "Security", - "description": "Known vulnerabilities, security advisories, response times" + "weight": 0.20, + "description": "Known vulnerabilities, CVE count, vulnerability patch cadence, SAST findings, signed releases" }, { - "id": "maintenance", - "name": "Maintenance", - "description": "Release cadence, issue response time, contributor activity" + "id": "maintainability", + "name": "Maintainability", + "weight": 0.15, + "description": "Commit frequency, test coverage, code complexity, open issue age, changelog/CI health" + }, + { + "id": "documentation", + "name": "Documentation", + "weight": 0.10, + "description": "API reference completeness, README quality, examples, changelog, docs site freshness" }, { "id": "community", "name": "Community Health", - "description": "Bus factor, code of conduct, funding, governance docs" + "weight": 0.10, + "description": "Contributor count, bus factor resilience, issue response time, star/fork trajectory, downstream dependents" }, { - "id": "code_quality", - "name": "Code Quality", - "description": "Test coverage, linting, type safety, complexity" + "id": "supply_chain", + "name": "Supply Chain", + "weight": 0.10, + "description": "Dependency count, transitive CVEs, SBOM presence, Sigstore/in-toto attestations, typosquatting distance" }, { - "id": "documentation", - "name": "Documentation", - "description": "README quality, API docs, examples, changelog" + "id": "velocity", + "name": "Improvement Velocity", + "weight": 0.05, + "description": "90-day trailing FTI score delta, CVE closure rate, test coverage changes, documentation improvements" + }, + { + "id": "governance", + "name": "Governance", + "weight": 0.15, + "description": "CI/system health grade, gate completion rate, separation of duties, ledger integrity, violation remediation" }, { - "id": "licensing", - "name": "Licensing", - "description": "License compatibility, patent grants, commercial use" + "id": "operational", + "name": "Operational", + "weight": 0.15, + "description": "Uptime SLA, incident frequency, MTTR, monitoring coverage, API p95 latency" } ], "context_factors": [ @@ -146,7 +164,7 @@ "faq": [ { "q": "How is FTI different from npm audit or Snyk?", - "a": "Those tools check for known vulnerabilities. FTI evaluates the overall trustworthiness of a package across 6 dimensions — security is just one. FTI also provides context-aware scores tailored to your specific needs." + "a": "Those tools check for known vulnerabilities. FTI evaluates the overall trustworthiness of a package across 8 dimensions — security is just one. FTI also provides context-aware scores tailored to your specific needs." }, { "q": "Can I dispute a score?", @@ -162,8 +180,8 @@ } ], "_meta": { - "generated_at": "2026-03-03T04:27:17.597587+00:00", - "source": "config/product_docs/fti_001.yaml", + "generated_at": "2026-03-27T00:00:00.000000+00:00", + "source": "config/product_docs/fti.yaml", "generator": "ba docs-generate" } -} \ No newline at end of file +} diff --git a/src/data/products/forgeos.ts b/src/data/products/forgeos.ts index 0168000..4d3b8d8 100644 --- a/src/data/products/forgeos.ts +++ b/src/data/products/forgeos.ts @@ -10,7 +10,7 @@ export default { href: '/products/forgeos/', ctaType: 'login' as const, - loginUrl: 'https://forgeos.synctek.io/', + loginUrl: 'https://forgeos.synctek.io/register', dashboardUrl: 'https://forgeos.synctek.io', support: { email: 'support@synctek.io', @@ -95,7 +95,7 @@ export default { ], overview: - 'ForgeOS is the governance OS for teams running agentic software pipelines. It is not an AI — it is the persistent enforcement, memory, and trust layer that sits between your AI agents and your infrastructure.\n\nEvery commit, every deploy, every inter-agent delegation passes through a configurable gate. Gates require artifacts — architecture approvals, QA sign-offs, security reviews — before the next phase unlocks. No artifact, no execution.\n\nThe audit ledger is Ed25519-signed and hash-chained. Every action is attributed, ordered, and tamper-evident. When something goes wrong, you trace it in seconds, not hours.\n\nSharedMind is the institutional memory layer — patterns, anti-patterns, and lessons persist across sessions and are surfaced automatically to any agent that connects. Your AI agents get smarter every cycle, without manual curation.\n\nShips as an MCP server (21 tools), a CLI (forge — 18 command groups, 49 subcommands), and a REST API (135+ endpoints). Works with any MCP-compatible agent: Claude, GPT, Gemini, or local models. Connect via MCP with your ForgeOS API key — your AI model keys stay with you. Raw source code stays local — ForgeOS analyzes project metadata (file structure, languages, dependencies) but never uploads file contents.', + 'ForgeOS is the governance OS for teams running agentic software pipelines. It is not an AI — it is the persistent enforcement, memory, and trust layer that sits between your AI agents and your infrastructure.\n\nEvery commit, every deploy, every inter-agent delegation passes through a configurable gate. Gates require artifacts — architecture approvals, QA sign-offs, security reviews — before the next phase unlocks. No artifact, no execution.\n\nThe audit ledger is Ed25519-signed and hash-chained. Every action is attributed, ordered, and tamper-evident. When something goes wrong, you trace it in seconds, not hours.\n\nSharedMind is the institutional memory layer — patterns, anti-patterns, and lessons persist across sessions and are surfaced automatically to any agent that connects. Your AI agents get smarter every cycle, without manual curation.\n\nShips as an MCP server (21 tools), a CLI (forge — 18 command groups, 49 subcommands), and a REST API (239 endpoints). Works with any MCP-compatible agent: Claude, GPT, Gemini, or local models. Connect via MCP with your ForgeOS API key — your AI model keys stay with you. Raw source code stays local — ForgeOS analyzes project metadata (file structure, languages, dependencies) but never uploads file contents.', tradeoffs: [ 'Commercial hosted service — the CLI is MIT-licensed, but the ForgeOS API requires a paid subscription.', diff --git a/src/data/products/specterqa-ios.ts b/src/data/products/specterqa-ios.ts new file mode 100644 index 0000000..89c23d8 --- /dev/null +++ b/src/data/products/specterqa-ios.ts @@ -0,0 +1,130 @@ +export default { + slug: 'specterqa-ios', + name: 'SpecterQA iOS', + tagline: 'The only iOS tester your agent can call.', + type: 'CLI Tool + MCP Server', + status: 'launched', + version: '11.3.0', + license: 'Elastic-2.0', + license_url: 'https://github.com/SyncTek-LLC/specterqa-ios/blob/main/LICENSE', + accentColor: '#BC8CFF', + + href: '/products/specterqa-ios/', + + ctaType: 'install' as const, + installCommand: "pip install 'specterqa-ios[mcp]'", + support: { + email: 'support@synctek.io', + github: 'SyncTek-LLC/specterqa-ios', + docs: 'https://github.com/SyncTek-LLC/specterqa-ios#readme', + }, + + distribution: { + pypi: 'specterqa-ios', + github: 'SyncTek-LLC/specterqa-ios', + mcp_entry: 'specterqa-ios-mcp', + agent_card: 'https://github.com/SyncTek-LLC/specterqa-ios/blob/main/.well-known/agent.json', + }, + + badges: [ + { type: 'github_stars', repo: 'SyncTek-LLC/specterqa-ios' }, + { type: 'license', value: 'Elastic-2.0' }, + { type: 'ci_status', repo: 'SyncTek-LLC/specterqa-ios' }, + ], + + features: [ + { + title: 'Record Once, Replay Free', + description: 'AI records test sessions using Claude vision. Deterministic engine replays in CI — zero API cost on reruns.', + icon: 'workflow', + }, + { + title: 'Agent-Native (19 MCP Tools)', + description: 'Full testing surface exposed as MCP tools. Claude Code, Claude Desktop, or any MCP-compatible orchestrator can drive iOS tests in plain English.', + icon: 'plug', + }, + { + title: 'Maestro Compatible', + description: 'Existing Maestro YAML files work natively. tapOn, inputText, assertVisible — all understood. Zero migration cost.', + icon: 'code', + }, + { + title: 'Parallel CI — 10x Faster', + description: 'Shared runner reuse and clone isolation. Run 10 replays in the time XCUITest runs 1. `--parallel N` flag.', + icon: 'workflow', + }, + { + title: '90% Tap Accuracy', + description: 'Set-of-Mark (SoM) prompting annotates the simulator screenshot before Claude taps. No coordinate guessing, no brittle selectors.', + icon: 'eye', + }, + { + title: 'BYOK — Full Data Control', + description: 'Bring your own Anthropic API key. SyncTek never sees it. Your test data never leaves your machine. 97% gross margin for us, full control for you.', + icon: 'shield', + }, + ], + + quickstart: [ + { command: "pip install 'specterqa-ios[mcp]'", description: 'Install CLI + MCP server' }, + { command: 'specterqa-ios setup', description: 'Verify Xcode + simulators' }, + { command: 'specterqa-ios init', description: 'Scaffold .specterqa/ project files' }, + { command: 'export ANTHROPIC_API_KEY=sk-ant-...', description: 'Set your API key (record phase only)' }, + { command: 'specterqa-ios run --product myapp --journey smoke', description: 'Record a test with Claude' }, + { command: 'specterqa-ios ci .specterqa/replays/', description: 'Replay all tests in CI (free)' }, + ], + + pricing: [ + { + tier: 'Trial', + price: 'Free', + description: '1 simulator, 3 runs/session. No credit card required. Get started immediately.', + }, + { + tier: 'Indie', + price: '$29/mo', + description: '2 simulators, unlimited runs. Solo developers and side projects.', + cta: 'Start free trial', + ctaUrl: 'https://synctek.io/products/specterqa-ios#pricing', + }, + { + tier: 'Pro', + price: '$99/mo', + description: '4 simulators, unlimited runs, parallel CI. The workhorse tier.', + cta: 'Start free trial', + ctaUrl: 'https://synctek.io/products/specterqa-ios#pricing', + }, + { + tier: 'Team', + price: '$299/mo', + description: '10 simulators, parallel CI, priority support. Built for mobile teams.', + cta: 'Start free trial', + ctaUrl: 'https://synctek.io/products/specterqa-ios#pricing', + }, + { + tier: 'Enterprise', + price: 'Custom', + description: 'Unlimited simulators, SLA, dedicated support, custom contracts.', + cta: 'Contact sales', + ctaUrl: 'mailto:sales@synctek.io', + }, + ], + + overview: + 'SpecterQA iOS is an AI-native iOS simulator testing tool built around one insight: use AI to record, use a deterministic engine to replay.\n\nYou pay for AI tokens exactly once. Claude drives your iOS simulator using vision and Set-of-Mark prompting — tapping elements accurately, filling forms, navigating flows — and saves every action as a deterministic YAML replay file. Every subsequent CI run executes that replay file without ever calling Claude. No AI tokens. No API cost. The same result, every time.\n\nThe MCP server exposes 19 tools, making SpecterQA natively callable from Claude Code, Claude Desktop, or any MCP-compatible orchestrator. It is also A2A discoverable via `.well-known/agent.json`. Your AI agent can boot a simulator, record a smoke test, and queue it for CI — all in a single session.\n\nMaestro users get a zero-cost migration path: existing YAML files work natively. `tapOn`, `inputText`, `assertVisible`, `assertNotVisible`, and `waitFor` are all understood without changes. Mix Maestro shorthand and SpecterQA native syntax in the same file.\n\nBYOK means your Anthropic API key stays with you. SyncTek never proxies it, stores it, or sees your test data. Your app binary, simulator state, and recordings stay on your machine.', + + costs: [ + { type: 'Initial record (smoke, ~5 taps)', range: '$0.05 - $0.15' }, + { type: 'Initial record (full journey, ~20 taps)', range: '$0.20 - $0.60' }, + { type: 'CI replay (any size)', range: '$0.00' }, + ], + + tradeoffs: [ + 'macOS + Xcode 15+ required — iOS Simulator is macOS-only. No Linux CI without a macOS runner.', + 'BYOK required — you must supply your own Anthropic API key for the record phase. Replay is free.', + 'Elastic License 2.0 — free for internal use; commercial redistribution or competing service use is restricted.', + 'Record phase requires network access to the Anthropic API. Replay is fully offline.', + 'Parallel CI (Pro tier and above) — Trial and Indie tiers run replays sequentially.', + 'Simulator-only — physical device testing is not currently supported.', + ], +} as const; diff --git a/src/data/repos.ts b/src/data/repos.ts index 1de9070..96f9986 100644 --- a/src/data/repos.ts +++ b/src/data/repos.ts @@ -10,15 +10,5 @@ export default { topics: ['testing', 'ai', 'playwright', 'cli'], featured: true, }, - { - name: 'specterqa-mcp', - org: 'SyncTek-LLC', - description: 'MCP server for SpecterQA integration with AI agents', - language: 'Python', - stars: 0, - license: 'MIT', - topics: ['mcp', 'ai', 'testing'], - featured: false, - }, ], } as const; diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index c8fe0a6..1a5ca9e 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -2,7 +2,6 @@ import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; import SEO from '../components/SEO.astro'; -import SupportWidget from '../components/SupportWidget.astro'; import '../styles/global.css'; interface Props { @@ -27,7 +26,6 @@ const { title, description, ogImage, ogType, article, jsonLd } = Astro.props; - + + +