@tera-system/pro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE.md +59 -0
  2. package/MANIFEST.json +24 -0
  3. package/README.md +190 -0
  4. package/RELEASES.md +44 -0
  5. package/WELCOME.md +35 -0
  6. package/agents/application-blueprint.md +412 -0
  7. package/agents/auditor.md +670 -0
  8. package/agents/design-reviewer.md +397 -0
  9. package/agents/domain-expert-agent.md +510 -0
  10. package/agents/domain-research-agent.md +360 -0
  11. package/agents/engineering-agent-dotnet.md +222 -0
  12. package/agents/engineering-agent-phaser.md +279 -0
  13. package/agents/engineering-agent-typescript.md +304 -0
  14. package/agents/engineering-agent.md +147 -0
  15. package/agents/monitor.md +400 -0
  16. package/agents/production-erp-expert.md +506 -0
  17. package/agents/project-knowledge-agent.md +271 -0
  18. package/agents/qa-agent.md +503 -0
  19. package/agents/tera-business-transformation-consultant.md +290 -0
  20. package/agents/tera-client-engagement.md +891 -0
  21. package/agents/tera-software-designer.md +242 -0
  22. package/agents/tera-strategic-advisor.md +325 -0
  23. package/agents/tera-system-evolution.md +764 -0
  24. package/agents/tera.md +526 -0
  25. package/agents/ui-designer.md +431 -0
  26. package/commands/tera-approve.md +36 -0
  27. package/commands/tera-diagnose.md +49 -0
  28. package/commands/tera-gate.md +42 -0
  29. package/commands/tera-help.md +43 -0
  30. package/commands/tera-new-project.md +37 -0
  31. package/commands/tera-plan.md +36 -0
  32. package/commands/tera-request-build.md +47 -0
  33. package/commands/tera-resume.md +36 -0
  34. package/commands/tera-review.md +54 -0
  35. package/commands/tera-status.md +40 -0
  36. package/commands/tera-update.md +50 -0
  37. package/core/project-control/templates/TASK_TEMPLATE.md +146 -0
  38. package/core/tera-system/AGENT_ACTIVATION_MATRIX.md +285 -0
  39. package/core/tera-system/AGENT_DEPENDENCY_MAP.md +117 -0
  40. package/core/tera-system/AGENT_GENERATION_TEMPLATE.md +312 -0
  41. package/core/tera-system/AGENT_PERMISSION_MODEL.md +343 -0
  42. package/core/tera-system/AIS_PROTOCOL.md +191 -0
  43. package/core/tera-system/TERA_AGENT_CONDUCT.md +102 -0
  44. package/core/tera-system/TERA_CONTINUOUS_IMPROVEMENT_POLICY.md +111 -0
  45. package/core/tera-system/TERA_DISTRIBUTION_POLICY.md +291 -0
  46. package/core/tera-system/TERA_LICENSE_GUARD.md +144 -0
  47. package/core/tera-system/TERA_PROJECT_DECISION.md +281 -0
  48. package/core/tera-system/TERA_USER_GUIDE.md +462 -0
  49. package/core/tera-system/TOOLING_AND_MCP_POLICY.md +285 -0
  50. package/core/tera-system/TeraApplicationQuestionBank.md +362 -0
  51. package/core/tera-system/TeraArchitectureMap.md +91 -0
  52. package/core/tera-system/TeraClientPolicy.md +366 -0
  53. package/core/tera-system/TeraHelperAgents.md +970 -0
  54. package/core/tera-system/TeraPolicyMap.md +131 -0
  55. package/core/tera-system/TeraPreExecutionGate.md +818 -0
  56. package/core/tera-system/TeraPreparationDocumentationGovernance.md +370 -0
  57. package/core/tera-system/TeraPricingPolicy.md +674 -0
  58. package/core/tera-system/TeraProjectIntakePolicy.md +164 -0
  59. package/core/tera-system/TeraScenarioStressTests.md +168 -0
  60. package/core/tera-system/TeraSubAgents.md +854 -0
  61. package/core/tera-system/TeraSystemMaintenanceChecklist.md +80 -0
  62. package/core/tera-system/TeraTokenPolicy.md +362 -0
  63. package/core/tera-system/Tera_Project_Preparation_Files.md +1045 -0
  64. package/core/tera-system/agent-helpers/application-blueprint-details.md +177 -0
  65. package/core/tera-system/client-helpers/tera-client-engagement-discovery-domains.md +99 -0
  66. package/core/tera-system/client-helpers/tera-client-engagement-gates.md +258 -0
  67. package/core/tera-system/client-helpers/tera-client-engagement-pricing.md +341 -0
  68. package/core/tera-system/client-helpers/tera-client-engagement-protocols.md +692 -0
  69. package/core/tera-system/consulting-helpers/BTCA_METHODOLOGY_FRAMEWORK.md +195 -0
  70. package/core/tera-system/consulting-helpers/BTCA_REPORT_TEMPLATES.md +266 -0
  71. package/core/tera-system/design-system/ACCESSIBILITY_RULES.md +31 -0
  72. package/core/tera-system/design-system/COMPONENT_LIBRARY_SCHEMA.md +46 -0
  73. package/core/tera-system/design-system/DESIGN_MD_INTEGRATION.md +59 -0
  74. package/core/tera-system/design-system/DESIGN_REVIEW_STANDARDS.md +241 -0
  75. package/core/tera-system/design-system/DESIGN_SOURCE_PROTOCOL.md +61 -0
  76. package/core/tera-system/design-system/DESIGN_SYSTEM_OVERVIEW.md +66 -0
  77. package/core/tera-system/design-system/DESIGN_TOKENS_SCHEMA.md +66 -0
  78. package/core/tera-system/design-system/EXTERNAL_REFERENCE_ANALYSIS.md +52 -0
  79. package/core/tera-system/design-system/FIGMA_INTEGRATION.md +138 -0
  80. package/core/tera-system/design-system/INTERNAL_KITS_INDEX.md +26 -0
  81. package/core/tera-system/design-system/LAYOUT_PATTERNS.md +52 -0
  82. package/core/tera-system/design-system/MOBILE_UI_UX_STANDARDS.md +342 -0
  83. package/core/tera-system/design-system/RTL_LTR_RULES.md +39 -0
  84. package/core/tera-system/design-system/UI_ACCEPTANCE_GATE.md +80 -0
  85. package/core/tera-system/design-system/kits/KIT_ADMIN_DASHBOARD.md +102 -0
  86. package/core/tera-system/engineering-governance/ENGINEERING_AGENT_RESPONSIBILITIES.md +210 -0
  87. package/core/tera-system/engineering-governance/ENGINEERING_BEST_PRACTICES.md +468 -0
  88. package/core/tera-system/engineering-governance/ENGINEERING_GOVERNANCE_GATE.md +131 -0
  89. package/core/tera-system/engineering-governance/ENGINEERING_REVIEW_CHECKLIST.md +129 -0
  90. package/core/tera-system/engineering-governance/QUALITY_GATE_THRESHOLDS.md +159 -0
  91. package/core/tera-system/engineering-helpers/engineering-agent-core.md +171 -0
  92. package/core/tera-system/knowledge-base/OPENHANDS_ARCHITECTURE_REFERENCE.md +243 -0
  93. package/core/tera-system/knowledge-base/manufacturing/00_INDEX.md +32 -0
  94. package/core/tera-system/knowledge-base/manufacturing/01_MANUFACTURING_ERP_CORE_CONCEPTS.md +7 -0
  95. package/core/tera-system/knowledge-base/manufacturing/02_SAP_MANUFACTURING_RESEARCH.md +7 -0
  96. package/core/tera-system/knowledge-base/manufacturing/03_DYNAMICS_365_MANUFACTURING_RESEARCH.md +7 -0
  97. package/core/tera-system/knowledge-base/manufacturing/04_ORACLE_MANUFACTURING_RESEARCH.md +7 -0
  98. package/core/tera-system/knowledge-base/manufacturing/05_ODOO_MANUFACTURING_RESEARCH.md +7 -0
  99. package/core/tera-system/knowledge-base/manufacturing/06_ERPNEXT_MANUFACTURING_RESEARCH.md +7 -0
  100. package/core/tera-system/knowledge-base/manufacturing/07_MANUFACTURING_COSTING_GUIDE.md +7 -0
  101. package/core/tera-system/knowledge-base/manufacturing/08_PRODUCTION_DISCOVERY_QUESTIONS.md +7 -0
  102. package/core/tera-system/knowledge-base/manufacturing/09_MANUFACTURING_BLUEPRINT_CHECKLIST.md +7 -0
  103. package/core/tera-system/knowledge-base/manufacturing/10_PRODUCTION_TEST_SCENARIOS.md +7 -0
  104. package/core/tera-system/knowledge-base/manufacturing/11_QUALITY_REWORK_AND_SCRAP_GUIDE.md +7 -0
  105. package/core/tera-system/knowledge-base/manufacturing/12_MRP_AND_PLANNING_GUIDE.md +7 -0
  106. package/core/tera-system/knowledge-base/manufacturing/13_LOCAL_AND_REGIONAL_MANUFACTURING_CONTEXT.md +7 -0
  107. package/core/tera-system/knowledge-base/manufacturing/14_VENDOR_COMPARISON_MATRIX.md +7 -0
  108. package/core/tera-system/product-standards/maintenance-apps/BEST_PRACTICES_DOMAIN.md +325 -0
  109. package/core/tera-system/product-standards/maintenance-apps/STANDARD_DEFINITION.md +142 -0
  110. package/core/tera-system/profiles/PROFILES_INDEX.md +57 -0
  111. package/core/tera-system/profiles/TEMPLATE.md +47 -0
  112. package/core/tera-system/profiles/dotnet-blazor-ef.md +76 -0
  113. package/core/tera-system/profiles/dotnet-razorpages-adonet.md +137 -0
  114. package/core/tera-system/profiles/dotnet-wpf-sqlite.md +159 -0
  115. package/core/tera-system/profiles/effect-bun-opencode.md +109 -0
  116. package/core/tera-system/profiles/flutter-mobile.md +369 -0
  117. package/core/tera-system/profiles/nextjs-prisma.md +110 -0
  118. package/core/tera-system/profiles/phaser-react-node.md +302 -0
  119. package/core/tera-system/profiles/react-pwa.md +97 -0
  120. package/core/tera-system/runtime/CLIENT_DISCOVERY_PROTOCOL.md +145 -0
  121. package/core/tera-system/runtime/DOMAIN_INTELLIGENCE_PROTOCOL.md +124 -0
  122. package/core/tera-system/runtime/MVP_DEFINITION_PROTOCOL.md +176 -0
  123. package/core/tera-system/runtime/TERA_RUNTIME_CHECKLISTS.md +646 -0
  124. package/core/tera-system/runtime/TERA_RUNTIME_PROTOCOLS.md +50 -0
  125. package/core/tera-system/runtime/TERA_RUNTIME_PROTOCOLS_CLIENT.md +355 -0
  126. package/core/tera-system/runtime/TERA_RUNTIME_PROTOCOLS_CORE.md +799 -0
  127. package/core/tera-system/runtime/TERA_RUNTIME_TEMPLATES.md +908 -0
  128. package/core/tera-system/runtime/TERA_RUNTIME_TEMPLATES_DELIVERY.md +584 -0
  129. package/core/tera-system/runtime/TERA_RUNTIME_TEMPLATES_PREPARATION.md +376 -0
  130. package/core/tera-system/runtime/TERA_SOLUTION_PREPARATION_PROTOCOL.md +335 -0
  131. package/core/tera-system/runtime/TERA_SOLUTION_PREPARATION_TEMPLATES.md +397 -0
  132. package/core/tera-system/runtime/VERSION_LIFECYCLE_PROTOCOL.md +296 -0
  133. package/core/tera-system/semgrep-rules/README.md +32 -0
  134. package/core/tera-system/semgrep-rules/tera-security.yml +66 -0
  135. package/core/tera-system/semgrep-rules/tera-standards.yml +49 -0
  136. package/core/tera-system/teranoo-ui/README.md +48 -0
  137. package/core/tera-system/teranoo-ui/components/button.tsx +51 -0
  138. package/core/tera-system/teranoo-ui/components/card.tsx +49 -0
  139. package/core/tera-system/teranoo-ui/components/dashboard-layout.tsx +36 -0
  140. package/core/tera-system/teranoo-ui/components/data-table.tsx +146 -0
  141. package/core/tera-system/teranoo-ui/components/empty-state.tsx +31 -0
  142. package/core/tera-system/teranoo-ui/components/kpi-card.tsx +42 -0
  143. package/core/tera-system/teranoo-ui/components/page-header.tsx +25 -0
  144. package/core/tera-system/teranoo-ui/components/search-input.tsx +40 -0
  145. package/core/tera-system/teranoo-ui/components/sidebar.tsx +66 -0
  146. package/core/tera-system/teranoo-ui/components/stats-card.tsx +37 -0
  147. package/core/tera-system/teranoo-ui/registry.json +77 -0
  148. package/core/tera-system/teranoo-ui/styles/teranoo-theme.css +61 -0
  149. package/opencode.tera.example.json +30 -0
  150. package/package.json +43 -0
  151. package/scripts/build-bundle.mjs +118 -0
  152. package/scripts/build.mjs +110 -0
  153. package/scripts/dev/mock-server.mjs +124 -0
  154. package/scripts/install.js +406 -0
  155. package/scripts/lib/bundle.mjs +120 -0
  156. package/scripts/lib/integrity.mjs +195 -0
  157. package/scripts/lib/license-gate.mjs +263 -0
  158. package/scripts/lib/license.mjs +90 -0
  159. package/scripts/lib/public-key.pem +3 -0
  160. package/scripts/preflight.mjs +55 -0
  161. package/scripts/tera-heartbeat.mjs +132 -0
  162. package/scripts/tera-license.mjs +63 -0
  163. package/scripts/tera-sync.mjs +116 -0
  164. package/tools/tera-clean.ps1 +97 -0
  165. package/tools/tera-fetch.ps1 +165 -0
  166. package/tools/tera-release.ps1 +96 -0
  167. package/tools/tera-schedule.ps1 +59 -0
  168. package/tools/tera-update.ps1 +472 -0
  169. package/tools/tera-watch.ps1 +154 -0
  170. package/tools/update-client-repositories.ps1 +92 -0
@@ -0,0 +1,66 @@
1
+ import * as React from "react"
2
+
3
+ interface SidebarItem {
4
+ label: string
5
+ icon?: React.ReactNode
6
+ href?: string
7
+ active?: boolean
8
+ children?: SidebarItem[]
9
+ }
10
+
11
+ interface SidebarProps {
12
+ items: SidebarItem[]
13
+ collapsed?: boolean
14
+ onToggle?: () => void
15
+ footer?: React.ReactNode
16
+ }
17
+
18
+ export function Sidebar({ items, collapsed, onToggle, footer }: SidebarProps) {
19
+ return (
20
+ <aside
21
+ className={`flex flex-col border-l border-[var(--teranoo-border)] bg-[var(--teranoo-background)] transition-all duration-300 ${
22
+ collapsed ? "w-16" : "w-64"
23
+ }`}
24
+ >
25
+ <div className="flex items-center justify-between p-4 border-b border-[var(--teranoo-border)]">
26
+ {!collapsed && (
27
+ <span className="font-semibold text-lg">Teranoo</span>
28
+ )}
29
+ <button
30
+ onClick={onToggle}
31
+ className="p-1 rounded-md hover:bg-[var(--teranoo-muted)]"
32
+ >
33
+ {collapsed ? "→" : "←"}
34
+ </button>
35
+ </div>
36
+
37
+ <nav className="flex-1 p-2 space-y-1">
38
+ {items.map((item, i) => (
39
+ <SidebarLink key={i} item={item} collapsed={collapsed} />
40
+ ))}
41
+ </nav>
42
+
43
+ {footer && (
44
+ <div className="p-4 border-t border-[var(--teranoo-border)]">
45
+ {footer}
46
+ </div>
47
+ )}
48
+ </aside>
49
+ )
50
+ }
51
+
52
+ function SidebarLink({ item, collapsed }: { item: SidebarItem; collapsed?: boolean }) {
53
+ return (
54
+ <a
55
+ href={item.href || "#"}
56
+ className={`flex items-center gap-3 px-3 py-2 rounded-[var(--teranoo-radius)] text-sm transition-colors ${
57
+ item.active
58
+ ? "bg-[var(--teranoo-primary)] text-[var(--teranoo-primary-foreground)]"
59
+ : "text-[var(--teranoo-foreground)] hover:bg-[var(--teranoo-muted)]"
60
+ }`}
61
+ >
62
+ {item.icon && <span className="h-4 w-4">{item.icon}</span>}
63
+ {!collapsed && <span>{item.label}</span>}
64
+ </a>
65
+ )
66
+ }
@@ -0,0 +1,37 @@
1
+ import * as React from "react"
2
+ import { Card, CardContent } from "./card"
3
+
4
+ interface StatsCardProps {
5
+ label: string
6
+ value: string | number
7
+ description?: string
8
+ trend?: "up" | "down" | "neutral"
9
+ }
10
+
11
+ export function StatsCard({ label, value, description, trend }: StatsCardProps) {
12
+ const trendIcon = trend === "up" ? "↑" : trend === "down" ? "↓" : "→"
13
+ const trendColor = trend === "up"
14
+ ? "text-[var(--teranoo-success)]"
15
+ : trend === "down"
16
+ ? "text-[var(--teranoo-danger)]"
17
+ : "text-[var(--teranoo-muted-foreground)]"
18
+
19
+ return (
20
+ <Card>
21
+ <CardContent className="p-4">
22
+ <div className="space-y-1">
23
+ <p className="text-xs text-[var(--teranoo-muted-foreground)]">{label}</p>
24
+ <div className="flex items-baseline gap-2">
25
+ <p className="text-2xl font-bold">{value}</p>
26
+ {trend && (
27
+ <span className={`text-sm ${trendColor}`}>{trendIcon}</span>
28
+ )}
29
+ </div>
30
+ {description && (
31
+ <p className="text-xs text-[var(--teranoo-muted-foreground)]">{description}</p>
32
+ )}
33
+ </div>
34
+ </CardContent>
35
+ </Card>
36
+ )
37
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "teranoo-ui",
3
+ "description": "Teranoo UI Registry — مكونات Tera المعتمدة لتطبيقات الزبائن",
4
+ "version": "1.0.0",
5
+ "registry": [
6
+ {
7
+ "name": "button",
8
+ "type": "components:ui",
9
+ "description": "زر Tera الأساسي — يمتد shadcn button مع ثيم Tera",
10
+ "dependencies": ["@radix-ui/react-slot"],
11
+ "files": ["components/button.tsx"]
12
+ },
13
+ {
14
+ "name": "card",
15
+ "type": "components:ui",
16
+ "description": "بطاقة Tera — تعرض محتوى بحدود وظل موحدين",
17
+ "dependencies": [],
18
+ "files": ["components/card.tsx"]
19
+ },
20
+ {
21
+ "name": "dashboard-layout",
22
+ "type": "components:ui",
23
+ "description": "هيكل لوحة تحكم كامل — Sidebar + Header + Main",
24
+ "dependencies": [],
25
+ "files": ["components/dashboard-layout.tsx"]
26
+ },
27
+ {
28
+ "name": "data-table",
29
+ "type": "components:ui",
30
+ "description": "جدول بيانات متقدم — فرز، فلتر، بحث، Pagination",
31
+ "dependencies": ["@tanstack/react-table"],
32
+ "files": ["components/data-table.tsx"]
33
+ },
34
+ {
35
+ "name": "kpi-card",
36
+ "type": "components:ui",
37
+ "description": "بطاقة KPI — عنوان، قيمة، مؤشر تغيير، أيقونة",
38
+ "dependencies": [],
39
+ "files": ["components/kpi-card.tsx"]
40
+ },
41
+ {
42
+ "name": "sidebar",
43
+ "type": "components:ui",
44
+ "description": "قائمة جانبية — عناصر قائمة مع أيقونات، قابلة للطي",
45
+ "dependencies": ["@radix-ui/react-dialog"],
46
+ "files": ["components/sidebar.tsx"]
47
+ },
48
+ {
49
+ "name": "stats-card",
50
+ "type": "components:ui",
51
+ "description": "بطاقة إحصائية — رقم، وصف، رسم بياني صغير",
52
+ "dependencies": [],
53
+ "files": ["components/stats-card.tsx"]
54
+ },
55
+ {
56
+ "name": "page-header",
57
+ "type": "components:ui",
58
+ "description": "عنوان صفحة موحّد — عنوان، وصف، أزرار إجراءات",
59
+ "dependencies": [],
60
+ "files": ["components/page-header.tsx"]
61
+ },
62
+ {
63
+ "name": "search-input",
64
+ "type": "components:ui",
65
+ "description": "حقل بحث موحّد — أيقونة، كتابة، مسح",
66
+ "dependencies": [],
67
+ "files": ["components/search-input.tsx"]
68
+ },
69
+ {
70
+ "name": "empty-state",
71
+ "type": "components:ui",
72
+ "description": "حالة عدم وجود بيانات — أيقونة، رسالة، زر إجراء",
73
+ "dependencies": [],
74
+ "files": ["components/empty-state.tsx"]
75
+ }
76
+ ]
77
+ }
@@ -0,0 +1,61 @@
1
+ /* ============================================
2
+ Teranoo Theme — ألوان Tera الموحّدة
3
+ استخدم هذا الملف في أي مشروع Tera UI
4
+ ============================================ */
5
+
6
+ :root {
7
+ /* الألوان الأساسية */
8
+ --teranoo-primary: #2563eb;
9
+ --teranoo-primary-foreground: #ffffff;
10
+ --teranoo-primary-hover: #1d4ed8;
11
+
12
+ --teranoo-secondary: #64748b;
13
+ --teranoo-secondary-foreground: #ffffff;
14
+
15
+ --teranoo-accent: #f59e0b;
16
+ --teranoo-accent-foreground: #1c1917;
17
+
18
+ --teranoo-success: #10b981;
19
+ --teranoo-warning: #f59e0b;
20
+ --teranoo-danger: #ef4444;
21
+ --teranoo-info: #3b82f6;
22
+
23
+ /* الخلفية والنص */
24
+ --teranoo-background: #ffffff;
25
+ --teranoo-foreground: #0f172a;
26
+ --teranoo-muted: #f1f5f9;
27
+ --teranoo-muted-foreground: #64748b;
28
+ --teranoo-border: #e2e8f0;
29
+ --teranoo-input: #e2e8f0;
30
+ --teranoo-ring: #2563eb;
31
+
32
+ /* الزوايا */
33
+ --teranoo-radius: 0.5rem;
34
+
35
+ /* الخطوط */
36
+ --teranoo-font-family: 'Cairo', 'Inter', sans-serif;
37
+ --teranoo-font-size-xs: 0.75rem;
38
+ --teranoo-font-size-sm: 0.875rem;
39
+ --teranoo-font-size-base: 1rem;
40
+ --teranoo-font-size-lg: 1.125rem;
41
+ --teranoo-font-size-xl: 1.25rem;
42
+ --teranoo-font-size-2xl: 1.5rem;
43
+
44
+ /* الظلال */
45
+ --teranoo-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
46
+ --teranoo-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
47
+ --teranoo-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
48
+ --teranoo-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
49
+
50
+ /* RTL */
51
+ --teranoo-direction: rtl;
52
+ }
53
+
54
+ /* وضع الظلام (اختياري) */
55
+ .dark {
56
+ --teranoo-primary: #3b82f6;
57
+ --teranoo-background: #0f172a;
58
+ --teranoo-foreground: #f8fafc;
59
+ --teranoo-muted: #1e293b;
60
+ --teranoo-border: #334155;
61
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "mcp": {
4
+ "playwright": {
5
+ "type": "local",
6
+ "command": ["npx", "-y", "@playwright/mcp"],
7
+ "enabled": true
8
+ },
9
+ "semgrep": {
10
+ "type": "local",
11
+ "command": ["npx", "-y", "mcp-server-semgrep"],
12
+ "enabled": true
13
+ },
14
+ "structurizr": {
15
+ "type": "local",
16
+ "command": [
17
+ "uv",
18
+ "run",
19
+ "--directory",
20
+ "structurizr-mcp",
21
+ "structurizr-mcp"
22
+ ],
23
+ "enabled": false,
24
+ "env": {
25
+ "STRUCTURIZR_WORKSPACE_DIR": "../architecture",
26
+ "STRUCTURIZR_URL": "http://localhost:8081"
27
+ }
28
+ }
29
+ }
30
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@tera-system/pro",
3
+ "version": "0.1.0",
4
+ "description": "Tera System Pro — commercial edition with enforced license gate, server sync, and heartbeat verification",
5
+ "license": "SEE LICENSE IN LICENSE.md",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=18"
9
+ },
10
+ "files": [
11
+ "agents",
12
+ "commands",
13
+ "core",
14
+ "tools",
15
+ "scripts",
16
+ "MANIFEST.json",
17
+ "opencode.tera.example.json",
18
+ "WELCOME.md",
19
+ "README.md",
20
+ "LICENSE.md",
21
+ "RELEASES.md"
22
+ ],
23
+ "scripts": {
24
+ "postinstall": "node scripts/install.js",
25
+ "tera-license": "node scripts/tera-license.mjs",
26
+ "tera-preflight": "node scripts/preflight.mjs",
27
+ "tera-sync": "node scripts/tera-sync.mjs",
28
+ "tera-heartbeat": "node scripts/tera-heartbeat.mjs",
29
+ "tera-bundle": "node scripts/build-bundle.mjs"
30
+ },
31
+ "keywords": [
32
+ "opencode",
33
+ "plugin",
34
+ "tera",
35
+ "governance",
36
+ "agents",
37
+ "commercial",
38
+ "license"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ }
43
+ }
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @tera-system/pro — Signed Core Bundle Builder
4
+ * --------------------------------------------------------------
5
+ * Generates a signed bundle of all core content (agents, commands,
6
+ * tera-system, tools) that the remote server will host as a static
7
+ * artifact. The installer/sync module downloads it, verifies the
8
+ * Ed25519 signature, validates hashes, and applies files.
9
+ *
10
+ * Usage:
11
+ * node scripts/build-bundle.mjs [--out artifacts/core-bundle.json]
12
+ *
13
+ * The private key is read from:
14
+ * TERA_PRIVATE_KEY_PATH (env) or
15
+ * ~/.tera/keys/production-private-key.pem
16
+ */
17
+ import { createHash } from "node:crypto";
18
+ import crypto from "node:crypto";
19
+ import fs from "node:fs";
20
+ import os from "node:os";
21
+ import path from "node:path";
22
+ import { fileURLToPath } from "node:url";
23
+
24
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
+ const ROOT = path.resolve(__dirname, "..");
26
+ const ART = path.join(ROOT, "artifacts");
27
+
28
+ const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8"));
29
+
30
+ function walkFiles(dir, base = dir) {
31
+ const out = [];
32
+ if (!fs.existsSync(dir)) return out;
33
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
34
+ const full = path.join(dir, e.name);
35
+ if (e.isDirectory()) out.push(...walkFiles(full, base));
36
+ else if (e.isFile()) {
37
+ out.push({ abs: full, rel: path.relative(base, full).split(path.sep).join("/") });
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+
43
+ function loadPrivateKey() {
44
+ const candidates = [
45
+ process.env.TERA_PRIVATE_KEY_PATH,
46
+ path.join(os.homedir(), ".tera", "keys", "production-private-key.pem"),
47
+ path.join(ROOT, "scripts", "lib", "dev-private-key.pem"),
48
+ ];
49
+ for (const c of candidates) {
50
+ if (c && fs.existsSync(c)) return fs.readFileSync(c, "utf8");
51
+ }
52
+ throw new Error("Private key not found. Set TERA_PRIVATE_KEY_PATH.");
53
+ }
54
+
55
+ const groups = [
56
+ { name: "agents", relDir: "agents" },
57
+ { name: "commands", relDir: "commands" },
58
+ { name: "tera-system", relDir: "core/tera-system" },
59
+ { name: "tools", relDir: "tools" },
60
+ ];
61
+
62
+ // Collect all bundle files
63
+ const files = [];
64
+ for (const g of groups) {
65
+ const srcDir = path.join(ROOT, g.relDir);
66
+ for (const f of walkFiles(srcDir)) {
67
+ files.push({ path: `${g.name}/${f.rel}`, content: fs.readFileSync(f.abs, "utf8") });
68
+ }
69
+ }
70
+
71
+ // Build manifest of hashes
72
+ const manifest = {};
73
+ for (const f of files) {
74
+ manifest[f.path] = createHash("sha256").update(f.content).digest("hex");
75
+ }
76
+
77
+ // Canonical payload to sign: sorted manifest lines
78
+ const canonical = Object.keys(manifest)
79
+ .sort()
80
+ .map((p) => `${p}:${manifest[p]}`)
81
+ .join("\n");
82
+ const canonicalHash = createHash("sha256").update(canonical).digest("hex");
83
+
84
+ const privateKey = loadPrivateKey();
85
+ const signature = crypto.sign(null, Buffer.from(canonicalHash), privateKey).toString("base64url");
86
+
87
+ const bundle = {
88
+ type: "tera-core-bundle",
89
+ schema: 1,
90
+ packageName: pkg.name,
91
+ packageVersion: pkg.version,
92
+ createdAt: new Date().toISOString(),
93
+ contentSha256: canonicalHash,
94
+ files: files.map((f) => ({ path: f.path, data: Buffer.from(f.content, "utf8").toString("base64url") })),
95
+ manifest,
96
+ signature,
97
+ };
98
+
99
+ const outPath = process.argv.includes("--out")
100
+ ? path.resolve(process.argv[process.argv.indexOf("--out") + 1])
101
+ : path.join(ART, `core-bundle-v${pkg.version}.signed.json`);
102
+
103
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
104
+ fs.writeFileSync(outPath, JSON.stringify(bundle, null, 2));
105
+
106
+ // Also write a compact version (index + manifest only, files fetched separately)
107
+ const compactPath = outPath.replace(/\.json$/, ".compact.json");
108
+ fs.writeFileSync(
109
+ compactPath,
110
+ JSON.stringify({ ...bundle, files: undefined }, null, 0)
111
+ );
112
+
113
+ console.log(`✔ signed bundle (${files.length} files)`);
114
+ console.log(` contentSha256 : ${canonicalHash}`);
115
+ console.log(` signature : ${signature.slice(0, 40)}...`);
116
+ console.log(` full : ${outPath}`);
117
+ console.log(` compact : ${compactPath}`);
118
+ console.log(` size(full) : ${(fs.statSync(outPath).size / 1024).toFixed(1)} KB`);
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @tera/core build script
4
+ * --------------------------------------------------------------
5
+ * Produces a repeatable, verifiable release artifact for the
6
+ * OpenCode addon. NON-DESTRUCTIVE: only (re)creates files under
7
+ * `artifacts/` and NEVER touches package source content.
8
+ *
9
+ * Steps:
10
+ * 1. Validate content counts against MANIFEST.json (self-check).
11
+ * 2. `npm pack` the current package -> artifacts/<name>-<version>.tgz
12
+ * 3. Compute per-content-group SHA256 + artifact SHA256.
13
+ * 4. Write artifacts/SHA256SUMS.txt (+ per-file group map).
14
+ *
15
+ * Usage:
16
+ * node scripts/build.mjs (default: version from package.json)
17
+ */
18
+ import { execSync } from "node:child_process";
19
+ import { createHash } from "node:crypto";
20
+ import fs from "node:fs";
21
+ import path from "node:path";
22
+ import { fileURLToPath } from "node:url";
23
+
24
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
+ const ROOT = path.resolve(__dirname, "..");
26
+ const ART = path.join(ROOT, "artifacts");
27
+
28
+ const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8"));
29
+ const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, "MANIFEST.json"), "utf8"));
30
+
31
+ const countFiles = (dir) =>
32
+ fs.existsSync(path.join(ROOT, dir))
33
+ ? (function walk(d) {
34
+ let n = 0;
35
+ for (const e of fs.readdirSync(d, { withFileTypes: true })) {
36
+ if (e.isDirectory()) n += walk(path.join(d, e.name));
37
+ else if (e.isFile()) n++;
38
+ }
39
+ return n;
40
+ })(path.join(ROOT, dir))
41
+ : 0;
42
+
43
+ const groupSha = (dir) => {
44
+ if (!fs.existsSync(path.join(ROOT, dir))) return null;
45
+ const lines = [];
46
+ (function walk(d) {
47
+ for (const e of fs.readdirSync(d, { withFileTypes: true })) {
48
+ const full = path.join(d, e.name);
49
+ if (e.isDirectory()) walk(full);
50
+ else if (e.isFile()) {
51
+ const h = createHash("sha256").update(fs.readFileSync(full)).digest("hex");
52
+ lines.push(`${path.relative(ROOT, full).split(path.sep).join("/")}:${h}`);
53
+ }
54
+ }
55
+ })(path.join(ROOT, dir));
56
+ lines.sort();
57
+ return createHash("sha256").update(lines.join("\n")).digest("hex");
58
+ };
59
+
60
+ /* 1. self-check counts vs manifest */
61
+ console.log("── self-check: content counts vs MANIFEST.json");
62
+ const checks = [
63
+ ["agents", "agents"],
64
+ ["commands", "commands"],
65
+ ["core/tera-system", "coreFiles"],
66
+ ];
67
+ let fail = false;
68
+ for (const [dir, key] of checks) {
69
+ const n = countFiles(dir);
70
+ const expected = manifest.content[key];
71
+ const ok = n === expected;
72
+ console.log(` ${dir.padEnd(16)} ${n} (manifest ${expected}) ${ok ? "OK" : "MISMATCH"}`);
73
+ if (!ok) fail = true;
74
+ }
75
+ if (fail) {
76
+ console.error("✖ Self-check failed — aborting build.");
77
+ process.exit(1);
78
+ }
79
+
80
+ /* 2. pack */
81
+ console.log("── npm pack");
82
+ fs.mkdirSync(ART, { recursive: true });
83
+ const tarball = execSync(`npm pack ${JSON.stringify(ROOT)} --pack-destination ${JSON.stringify(ART)} --silent`, { cwd: ROOT, encoding: "utf8" }).trim();
84
+ console.log(` artifact: ${tarball}`);
85
+
86
+ /* 3. hashes */
87
+ const artPath = path.join(ART, tarball);
88
+ const artHash = createHash("sha256").update(fs.readFileSync(artPath)).digest("hex");
89
+ console.log(` SHA256 : ${artHash}`);
90
+
91
+ const groupHashes = {
92
+ agents: groupSha("agents"),
93
+ commands: groupSha("commands"),
94
+ "core/tera-system": groupSha("core/tera-system"),
95
+ tools: groupSha("tools"),
96
+ "core/project-control": groupSha("core/project-control"),
97
+ };
98
+ console.log(" group hashes:");
99
+ for (const [g, h] of Object.entries(groupHashes)) console.log(` ${g.padEnd(20)} ${h ?? "(n/a)"}`);
100
+
101
+ /* 4. write SHA256SUMS + group map + sync MANIFEST.json (single source of truth) */
102
+ fs.writeFileSync(path.join(ART, "SHA256SUMS.txt"), `${artHash} ${tarball}\n`);
103
+ fs.writeFileSync(path.join(ART, "GROUPS.json"), JSON.stringify({ version: pkg.version, builtAt: new Date().toISOString(), sha256: groupHashes }, null, 2));
104
+ manifest.sha256 = groupHashes;
105
+ manifest.version = pkg.version;
106
+ manifest.builtAt = new Date().toISOString().slice(0, 10);
107
+ fs.writeFileSync(path.join(ROOT, "MANIFEST.json"), JSON.stringify(manifest, null, 2) + "\n");
108
+ console.log(" wrote SHA256SUMS.txt + GROUPS.json + synced MANIFEST.json");
109
+
110
+ console.log("\n✔ build complete — artifact ready in artifacts/");
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @tera-system/pro — Mock License & Bundle Server (dev/testing)
4
+ * --------------------------------------------------------------
5
+ * Simulates the teranoo.com backend locally so the whole sync +
6
+ * license flow can be verified WITHOUT the real website.
7
+ *
8
+ * Endpoints:
9
+ * GET /api/tera-system/bundle → signed core bundle (JSON)
10
+ * GET /api/tera-system/health → simple health check
11
+ * POST /api/license/verify → validate license key
12
+ * POST /api/license/heartbeat → heartbeat (ok if key valid)
13
+ * POST /api/license/activate → activate a key
14
+ *
15
+ * Usage:
16
+ * node scripts/dev/mock-server.mjs [--port 3200] [--bundle path]
17
+ *
18
+ * Env:
19
+ * TERA_MOCK_BUNDLE — path to signed bundle JSON
20
+ * TERA_MOCK_PORT — port (default 3200)
21
+ */
22
+ import fs from "node:fs";
23
+ import http from "node:http";
24
+ import os from "node:os";
25
+ import path from "node:path";
26
+ import { fileURLToPath } from "node:url";
27
+ import { parseLicenseKey } from "../lib/license.mjs";
28
+
29
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
30
+ const ROOT = path.resolve(__dirname, "..", "..");
31
+
32
+ const args = process.argv.slice(2);
33
+ function argVal(name, def) {
34
+ const i = args.indexOf(name);
35
+ return i >= 0 && args[i + 1] ? args[i + 1] : def;
36
+ }
37
+
38
+ const PORT = Number(process.env.TERA_MOCK_PORT || argVal("--port", "3200"));
39
+ const BUNDLE_PATH = path.resolve(
40
+ process.env.TERA_MOCK_BUNDLE || argVal("--bundle", "") || path.join(ROOT, "artifacts", "core-bundle-v0.1.0.signed.json")
41
+ );
42
+
43
+ // In-memory license store for mock
44
+ const licenses = new Map();
45
+
46
+ function licenseFromKey(key) {
47
+ const parsed = parseLicenseKey(key);
48
+ if (!parsed.ok) return { valid: false, reason: parsed.reason };
49
+ const t = parsed.payload;
50
+ const expires = new Date(t.expiresAt).getTime();
51
+ const now = Date.now();
52
+ if (now > expires) return { valid: false, reason: "expired", expiresAt: t.expiresAt };
53
+ return { valid: true, tier: t.tier, project: t.project, expiresAt: t.expiresAt, seats: t.seats };
54
+ }
55
+
56
+ const server = http.createServer(async (req, res) => {
57
+ const url = new URL(req.url, `http://localhost:${PORT}`);
58
+ const body = await new Promise((resolve) => {
59
+ let data = "";
60
+ req.on("data", (c) => (data += c));
61
+ req.on("end", () => resolve(data));
62
+ });
63
+ let json = {};
64
+ try {
65
+ json = body ? JSON.parse(body) : {};
66
+ } catch {}
67
+
68
+ const send = (code, obj) => {
69
+ res.writeHead(code, { "Content-Type": "application/json" });
70
+ res.end(JSON.stringify(obj));
71
+ };
72
+
73
+ // ---- GET /api/tera-system/health ----
74
+ if (url.pathname === "/api/tera-system/health" || url.pathname === "/health") {
75
+ return send(200, { ok: true, service: "tera-mock", time: new Date().toISOString() });
76
+ }
77
+
78
+ // ---- GET /api/tera-system/bundle ----
79
+ if (url.pathname === "/api/tera-system/bundle" && req.method === "GET") {
80
+ if (!fs.existsSync(BUNDLE_PATH)) {
81
+ return send(404, { ok: false, error: `bundle not found: ${BUNDLE_PATH}` });
82
+ }
83
+ const bundle = JSON.parse(fs.readFileSync(BUNDLE_PATH, "utf8"));
84
+ res.writeHead(200, { "Content-Type": "application/json" });
85
+ res.end(JSON.stringify(bundle));
86
+ return;
87
+ }
88
+
89
+ // ---- POST /api/license/verify ----
90
+ if (url.pathname === "/api/license/verify" && req.method === "POST") {
91
+ const result = licenseFromKey(json.licenseKey);
92
+ if (!result.valid) return send(200, { valid: false, state: "Invalid", reason: result.reason });
93
+ return send(200, { valid: true, state: "Active", ...result, reason: "active" });
94
+ }
95
+
96
+ // ---- POST /api/license/heartbeat ----
97
+ if (url.pathname === "/api/license/heartbeat" && req.method === "POST") {
98
+ const result = licenseFromKey(json.licenseKey);
99
+ if (!result.valid) return send(200, { valid: false, reason: result.reason, ok: false });
100
+ return send(200, { valid: true, ok: true, expiresAt: result.expiresAt, tier: result.tier });
101
+ }
102
+
103
+ // ---- POST /api/license/activate ----
104
+ if (url.pathname === "/api/license/activate" && req.method === "POST") {
105
+ const result = licenseFromKey(json.licenseKey);
106
+ if (!result.valid) return send(400, { ok: false, error: result.reason });
107
+ licenses.set(json.licenseKey, { activatedAt: new Date().toISOString(), ...result });
108
+ return send(200, { ok: true, state: "Active", ...result });
109
+ }
110
+
111
+ return send(404, { ok: false, error: `unknown endpoint: ${url.pathname}` });
112
+ });
113
+
114
+ server.listen(PORT, () => {
115
+ console.log(`\n✔ Mock server running on http://localhost:${PORT}`);
116
+ console.log(` bundle : ${BUNDLE_PATH}`);
117
+ console.log(` exists : ${fs.existsSync(BUNDLE_PATH)}`);
118
+ console.log(` endpoints:`);
119
+ console.log(` GET /api/tera-system/bundle`);
120
+ console.log(` GET /api/tera-system/health`);
121
+ console.log(` POST /api/license/verify`);
122
+ console.log(` POST /api/license/heartbeat`);
123
+ console.log(` POST /api/license/activate\n`);
124
+ });