tradingcodex 0.1.0__py3-none-any.whl
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.
- apps/__init__.py +1 -0
- apps/audit/__init__.py +1 -0
- apps/audit/admin.py +6 -0
- apps/audit/apps.py +8 -0
- apps/audit/migrations/0001_initial.py +35 -0
- apps/audit/migrations/__init__.py +0 -0
- apps/audit/models.py +22 -0
- apps/harness/__init__.py +1 -0
- apps/harness/admin.py +6 -0
- apps/harness/apps.py +8 -0
- apps/harness/migrations/0001_initial.py +35 -0
- apps/harness/migrations/__init__.py +0 -0
- apps/harness/models.py +22 -0
- apps/harness/templatetags/__init__.py +1 -0
- apps/integrations/__init__.py +1 -0
- apps/integrations/admin.py +6 -0
- apps/integrations/apps.py +8 -0
- apps/integrations/migrations/0001_initial.py +29 -0
- apps/integrations/migrations/__init__.py +0 -0
- apps/integrations/models.py +16 -0
- apps/integrations/services.py +31 -0
- apps/mcp/__init__.py +1 -0
- apps/mcp/admin.py +20 -0
- apps/mcp/apps.py +8 -0
- apps/mcp/migrations/0001_initial.py +168 -0
- apps/mcp/migrations/__init__.py +0 -0
- apps/mcp/models.py +154 -0
- apps/mcp/services.py +327 -0
- apps/orders/__init__.py +1 -0
- apps/orders/admin.py +6 -0
- apps/orders/apps.py +8 -0
- apps/orders/migrations/0001_initial.py +79 -0
- apps/orders/migrations/__init__.py +0 -0
- apps/orders/models.py +66 -0
- apps/orders/services.py +107 -0
- apps/policy/__init__.py +1 -0
- apps/policy/admin.py +6 -0
- apps/policy/apps.py +8 -0
- apps/policy/migrations/0001_initial.py +75 -0
- apps/policy/migrations/__init__.py +0 -0
- apps/policy/models.py +61 -0
- apps/policy/services.py +110 -0
- apps/portfolio/__init__.py +1 -0
- apps/portfolio/admin.py +6 -0
- apps/portfolio/apps.py +8 -0
- apps/portfolio/migrations/0001_initial.py +67 -0
- apps/portfolio/migrations/__init__.py +0 -0
- apps/portfolio/models.py +53 -0
- apps/research/__init__.py +1 -0
- apps/research/admin.py +1 -0
- apps/research/apps.py +8 -0
- apps/research/migrations/__init__.py +0 -0
- apps/research/models.py +1 -0
- apps/workflows/__init__.py +1 -0
- apps/workflows/admin.py +6 -0
- apps/workflows/apps.py +8 -0
- apps/workflows/migrations/0001_initial.py +51 -0
- apps/workflows/migrations/__init__.py +0 -0
- apps/workflows/models.py +44 -0
- tradingcodex-0.1.0.dist-info/METADATA +337 -0
- tradingcodex-0.1.0.dist-info/RECORD +254 -0
- tradingcodex-0.1.0.dist-info/WHEEL +5 -0
- tradingcodex-0.1.0.dist-info/entry_points.txt +2 -0
- tradingcodex-0.1.0.dist-info/licenses/LICENSE +202 -0
- tradingcodex-0.1.0.dist-info/licenses/NOTICE +24 -0
- tradingcodex-0.1.0.dist-info/top_level.txt +4 -0
- tradingcodex_cli/__init__.py +1 -0
- tradingcodex_cli/__main__.py +124 -0
- tradingcodex_cli/commands/__init__.py +2 -0
- tradingcodex_cli/commands/bootstrap.py +157 -0
- tradingcodex_cli/commands/db.py +36 -0
- tradingcodex_cli/commands/doctor.py +230 -0
- tradingcodex_cli/commands/mcp.py +186 -0
- tradingcodex_cli/commands/orders.py +89 -0
- tradingcodex_cli/commands/policy.py +21 -0
- tradingcodex_cli/commands/profile.py +110 -0
- tradingcodex_cli/commands/research.py +76 -0
- tradingcodex_cli/commands/skills.py +93 -0
- tradingcodex_cli/commands/strategies.py +67 -0
- tradingcodex_cli/commands/subagents.py +106 -0
- tradingcodex_cli/commands/utils.py +134 -0
- tradingcodex_cli/commands/workspaces.py +53 -0
- tradingcodex_cli/generator.py +234 -0
- tradingcodex_cli/mcp_stdio.py +26 -0
- tradingcodex_cli/service_autostart.py +127 -0
- tradingcodex_service/__init__.py +5 -0
- tradingcodex_service/admin.py +1 -0
- tradingcodex_service/api.py +486 -0
- tradingcodex_service/application/__init__.py +2 -0
- tradingcodex_service/application/agents.py +1470 -0
- tradingcodex_service/application/audit.py +71 -0
- tradingcodex_service/application/common.py +88 -0
- tradingcodex_service/application/components.py +299 -0
- tradingcodex_service/application/harness.py +747 -0
- tradingcodex_service/application/markdown_preview.py +179 -0
- tradingcodex_service/application/orders.py +404 -0
- tradingcodex_service/application/policy.py +150 -0
- tradingcodex_service/application/portfolio.py +166 -0
- tradingcodex_service/application/research.py +356 -0
- tradingcodex_service/application/runtime.py +321 -0
- tradingcodex_service/asgi.py +6 -0
- tradingcodex_service/mcp_http.py +59 -0
- tradingcodex_service/mcp_runtime.py +565 -0
- tradingcodex_service/settings.py +91 -0
- tradingcodex_service/templates/web/activity.html +24 -0
- tradingcodex_service/templates/web/agent_skills.html +111 -0
- tradingcodex_service/templates/web/agents.html +121 -0
- tradingcodex_service/templates/web/base.html +150 -0
- tradingcodex_service/templates/web/dashboard.html +109 -0
- tradingcodex_service/templates/web/fragments/role_inspector.html +81 -0
- tradingcodex_service/templates/web/fragments/starter_prompt.html +24 -0
- tradingcodex_service/templates/web/fragments/topology_canvas.html +85 -0
- tradingcodex_service/templates/web/harness.html +87 -0
- tradingcodex_service/templates/web/mcp_router.html +250 -0
- tradingcodex_service/templates/web/orders.html +68 -0
- tradingcodex_service/templates/web/policy.html +81 -0
- tradingcodex_service/templates/web/portfolio.html +52 -0
- tradingcodex_service/templates/web/research.html +73 -0
- tradingcodex_service/templates/web/starter_prompt.html +40 -0
- tradingcodex_service/templates/web/strategies.html +74 -0
- tradingcodex_service/urls.py +42 -0
- tradingcodex_service/version.py +1 -0
- tradingcodex_service/web.py +885 -0
- tradingcodex_service/wsgi.py +6 -0
- workspace_templates/__init__.py +1 -0
- workspace_templates/modules/audit/files/.tradingcodex/audit/README.md +5 -0
- workspace_templates/modules/audit/files/trading/audit/.gitkeep +1 -0
- workspace_templates/modules/audit/module.json +16 -0
- workspace_templates/modules/codex-base/files/.codex/config.toml +272 -0
- workspace_templates/modules/codex-base/files/.codex/hooks/tradingcodex_hook.py +173 -0
- workspace_templates/modules/codex-base/files/.codex/hooks.json +105 -0
- workspace_templates/modules/codex-base/files/.codex/prompts/base_instructions/head-manager.md +129 -0
- workspace_templates/modules/codex-base/files/.codex/rules/tradingcodex.rules +50 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/capabilities.yaml +56 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/cli.py +16 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/config.yaml +53 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/policies/policy-bindings.yaml +16 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/policies/principals.yaml +17 -0
- workspace_templates/modules/codex-base/files/.tradingcodex/policies/roles.yaml +27 -0
- workspace_templates/modules/codex-base/files/AGENTS.md +56 -0
- workspace_templates/modules/codex-base/files/pyproject.toml +13 -0
- workspace_templates/modules/codex-base/files/tcx +35 -0
- workspace_templates/modules/codex-base/module.json +17 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/policies/access-policies.yaml +39 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/policies/restricted-list.yaml +6 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/approval_receipt.schema.json +14 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/audit_event.schema.json +11 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/evidence_pack.schema.json +16 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/execution_result.schema.json +12 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/fundamental_report.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/news_report.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/order_intent.schema.json +30 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/portfolio_review.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/postmortem_report.schema.json +14 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/risk_report.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/technical_report.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/thesis.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/schemas/valuation.schema.json +15 -0
- workspace_templates/modules/enforcement-guardrails/files/.tradingcodex/scripts/validate-order-intent.py +15 -0
- workspace_templates/modules/enforcement-guardrails/module.json +19 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/execution-operator.toml +71 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/fundamental-analyst.toml +62 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/instrument-analyst.toml +64 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/macro-analyst.toml +64 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/news-analyst.toml +63 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/portfolio-manager.toml +62 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/risk-manager.toml +65 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/technical-analyst.toml +63 -0
- workspace_templates/modules/fixed-subagents/files/.codex/agents/valuation-analyst.toml +59 -0
- workspace_templates/modules/fixed-subagents/files/.tradingcodex/mainagent/head-manager.yaml +66 -0
- workspace_templates/modules/fixed-subagents/files/.tradingcodex/mainagent/skill-change-proposals/.gitkeep +1 -0
- workspace_templates/modules/fixed-subagents/files/.tradingcodex/mainagent/subagent-registry.yaml +56 -0
- workspace_templates/modules/fixed-subagents/module.json +23 -0
- workspace_templates/modules/guidance-guardrails/files/.tradingcodex/guidance/guardrails.md +17 -0
- workspace_templates/modules/guidance-guardrails/files/.tradingcodex/guidance/task-quality-checklist.md +37 -0
- workspace_templates/modules/guidance-guardrails/module.json +18 -0
- workspace_templates/modules/information-barriers/files/.tradingcodex/policies/information-barriers.yaml +211 -0
- workspace_templates/modules/information-barriers/files/.tradingcodex/secrets.md +9 -0
- workspace_templates/modules/information-barriers/files/trading/approvals/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/market-data/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/orders/approved/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/orders/draft/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/orders/executed/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/orders/rejected/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/portfolio/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/fundamental/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/instrument/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/macro/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/news/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/policy/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/portfolio/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/postmortem/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/risk/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/technical/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/reports/valuation/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/files/trading/research/.gitkeep +1 -0
- workspace_templates/modules/information-barriers/module.json +19 -0
- workspace_templates/modules/paper-trading/files/.tradingcodex/mcp/adapters/paper-trading.py +4 -0
- workspace_templates/modules/paper-trading/module.json +16 -0
- workspace_templates/modules/postmortem/files/.tradingcodex/workflows/postmortem.yaml +12 -0
- workspace_templates/modules/postmortem/module.json +16 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/investment-workflow-map/SKILL.md +106 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/investment-workflow-map/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/manage-optional-skills/SKILL.md +101 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/manage-optional-skills/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/manage-subagents/SKILL.md +140 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/manage-subagents/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/orchestrate-workflow/SKILL.md +140 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/orchestrate-workflow/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/postmortem/SKILL.md +31 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/postmortem/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/scenario-quality-gates/SKILL.md +138 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/scenario-quality-gates/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/strategy-creator/SKILL.md +109 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/strategy-creator/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/synthesize-decision/SKILL.md +54 -0
- workspace_templates/modules/repo-skills/files/.agents/skills/synthesize-decision/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/execution-operator/execute-paper-order/SKILL.md +35 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/execution-operator/execute-paper-order/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/fundamental-analyst/fundamental-analysis/SKILL.md +46 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/fundamental-analyst/fundamental-analysis/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/instrument-analyst/instrument-analysis/SKILL.md +40 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/instrument-analyst/instrument-analysis/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/macro-analyst/macro-analysis/SKILL.md +40 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/macro-analyst/macro-analysis/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/news-analyst/news-analysis/SKILL.md +43 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/news-analyst/news-analysis/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/portfolio-manager/create-order-intent/SKILL.md +46 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/portfolio-manager/create-order-intent/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/portfolio-manager/portfolio-review/SKILL.md +44 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/portfolio-manager/portfolio-review/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/approve-order/SKILL.md +38 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/approve-order/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/policy-review/SKILL.md +43 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/policy-review/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/review-risk/SKILL.md +45 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/risk-manager/review-risk/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/shared/collect-evidence/SKILL.md +46 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/shared/collect-evidence/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/shared/external-data-source-gate/SKILL.md +66 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/shared/external-data-source-gate/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/technical-analyst/technical-analysis/SKILL.md +43 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/technical-analyst/technical-analysis/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/valuation-analyst/valuation-review/SKILL.md +47 -0
- workspace_templates/modules/repo-skills/files/.tradingcodex/subagents/skills/valuation-analyst/valuation-review/agents/openai.yaml +6 -0
- workspace_templates/modules/repo-skills/module.json +37 -0
- workspace_templates/modules/stub-execution/files/.tradingcodex/mcp/adapters/stub-execution.py +4 -0
- workspace_templates/modules/stub-execution/module.json +15 -0
- workspace_templates/modules/tradingcodex-mcp/files/.tradingcodex/mcp/adapters/live-adapter.contract.md +25 -0
- workspace_templates/modules/tradingcodex-mcp/files/.tradingcodex/mcp/enforcer/README.md +5 -0
- workspace_templates/modules/tradingcodex-mcp/files/.tradingcodex/mcp/gateway/README.md +8 -0
- workspace_templates/modules/tradingcodex-mcp/files/.tradingcodex/mcp/server.py +27 -0
- workspace_templates/modules/tradingcodex-mcp/files/.tradingcodex/mcp/smoke-call.py +18 -0
- workspace_templates/modules/tradingcodex-mcp/module.json +24 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<section class="tc-topology-shell" aria-label="tcx harness topology"
|
|
2
|
+
x-data="{
|
|
3
|
+
selectedRole: '{{ selected_role.role }}',
|
|
4
|
+
edgeGroups: {
|
|
5
|
+
'dispatch': true,
|
|
6
|
+
'research-handoff': true,
|
|
7
|
+
'portfolio-risk-gate': true,
|
|
8
|
+
'approval-gate': true,
|
|
9
|
+
'execution-gate': true
|
|
10
|
+
}
|
|
11
|
+
}">
|
|
12
|
+
<div class="tc-canvas-toolbar">
|
|
13
|
+
<div>
|
|
14
|
+
<span class="tc-eyebrow">Harness topology</span>
|
|
15
|
+
<strong>Roles, gates, and MCP boundary</strong>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="tc-edge-filter" aria-label="Edge groups">
|
|
20
|
+
{% for group in topology.edge_groups %}
|
|
21
|
+
<label>
|
|
22
|
+
<input type="checkbox" x-model="edgeGroups['{{ group.key }}']">
|
|
23
|
+
<span>{{ group.label }}</span>
|
|
24
|
+
</label>
|
|
25
|
+
{% endfor %}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="tc-edge-contracts" aria-label="Handoff edge contracts">
|
|
29
|
+
{% for group in topology.edge_groups %}
|
|
30
|
+
<span x-show="edgeGroups['{{ group.key }}']"><strong>{{ group.label }}:</strong> {{ group.contract }}</span>
|
|
31
|
+
{% endfor %}
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="tc-canvas-grid">
|
|
35
|
+
<div class="tc-canvas-stage">
|
|
36
|
+
<div class="tc-canvas-zoom">
|
|
37
|
+
<svg class="tc-topology-svg" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
|
|
38
|
+
<defs>
|
|
39
|
+
<marker id="tc-arrow" markerWidth="5" markerHeight="5" refX="4.5" refY="2.5" orient="auto">
|
|
40
|
+
<path d="M0,0 L5,2.5 L0,5 Z"></path>
|
|
41
|
+
</marker>
|
|
42
|
+
</defs>
|
|
43
|
+
<line class="tc-boundary-line" x1="{{ topology.boundary.x }}" y1="{{ topology.boundary.y1 }}" x2="{{ topology.boundary.x }}" y2="{{ topology.boundary.y2 }}"></line>
|
|
44
|
+
{% for edge in topology.edges %}
|
|
45
|
+
<polyline
|
|
46
|
+
x-show="edgeGroups['{{ edge.group }}']"
|
|
47
|
+
class="tc-edge tc-edge--{{ edge.group }}"
|
|
48
|
+
points="{{ edge.source_x }},{{ edge.source_y }} {{ edge.source_x }},{{ edge.mid_y }} {{ edge.target_x }},{{ edge.mid_y }} {{ edge.target_x }},{{ edge.target_y }}"
|
|
49
|
+
marker-end="url(#tc-arrow)"></polyline>
|
|
50
|
+
{% endfor %}
|
|
51
|
+
</svg>
|
|
52
|
+
|
|
53
|
+
<div class="tc-boundary-badge" style="--x: {{ topology.boundary.x }}%; --y: {{ topology.boundary.y1 }}%;">
|
|
54
|
+
<strong>{{ topology.boundary.label }}</strong>
|
|
55
|
+
<span>{{ topology.boundary.summary }}</span>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
{% for layer in topology.layers %}
|
|
59
|
+
<div class="tc-layer-label" style="--y: {{ layer.y }}%;">
|
|
60
|
+
<span>{{ layer.label }}</span>
|
|
61
|
+
</div>
|
|
62
|
+
{% endfor %}
|
|
63
|
+
|
|
64
|
+
{% for node in topology.nodes %}
|
|
65
|
+
<button
|
|
66
|
+
type="button"
|
|
67
|
+
class="tc-node tc-node--{{ node.group }}"
|
|
68
|
+
:class="{ 'is-selected': selectedRole === '{{ node.role }}' }"
|
|
69
|
+
style="--x: {{ node.x }}%; --y: {{ node.y }}%;"
|
|
70
|
+
@click="selectedRole = '{{ node.role }}'"
|
|
71
|
+
hx-get="{% url 'web-role-inspector' role=node.role %}"
|
|
72
|
+
hx-target="#role-inspector"
|
|
73
|
+
hx-swap="innerHTML">
|
|
74
|
+
<span>{{ node.label }}</span>
|
|
75
|
+
<small>{{ node.skills_count }} skills · {{ node.tools_count }} tools</small>
|
|
76
|
+
</button>
|
|
77
|
+
{% endfor %}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<aside id="role-inspector" class="tc-inspector" aria-live="polite">
|
|
82
|
+
{% include "web/fragments/role_inspector.html" %}
|
|
83
|
+
</aside>
|
|
84
|
+
</div>
|
|
85
|
+
</section>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{% extends "web/base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Harness Topology | tcx{% endblock %}
|
|
4
|
+
{% block page_label %}Harness{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
{% include "web/fragments/topology_canvas.html" %}
|
|
8
|
+
|
|
9
|
+
<section class="tc-section-grid">
|
|
10
|
+
<article class="tc-panel">
|
|
11
|
+
<div class="tc-panel-head">
|
|
12
|
+
<span class="tc-eyebrow">Health checks</span>
|
|
13
|
+
<h2>Harness status</h2>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="tc-check-grid">
|
|
16
|
+
{% for check in health.checks %}
|
|
17
|
+
<div>
|
|
18
|
+
<span class="tc-pill tc-pill--{{ check.status }}">{{ check.status }}</span>
|
|
19
|
+
<strong>{{ check.label }}</strong>
|
|
20
|
+
<small>{{ check.value }}</small>
|
|
21
|
+
</div>
|
|
22
|
+
{% endfor %}
|
|
23
|
+
</div>
|
|
24
|
+
</article>
|
|
25
|
+
|
|
26
|
+
<aside class="tc-panel">
|
|
27
|
+
<div class="tc-panel-head">
|
|
28
|
+
<span class="tc-eyebrow">MCP boundary</span>
|
|
29
|
+
<h2>Execution gate</h2>
|
|
30
|
+
</div>
|
|
31
|
+
<ul class="tc-plain-list">
|
|
32
|
+
<li>Web does not spawn subagents.</li>
|
|
33
|
+
<li>Web does not approve or submit orders.</li>
|
|
34
|
+
<li>Paper/stub execution stays behind policy checks.</li>
|
|
35
|
+
</ul>
|
|
36
|
+
</aside>
|
|
37
|
+
</section>
|
|
38
|
+
|
|
39
|
+
<details class="tc-details tc-diagnostics">
|
|
40
|
+
<summary>Harness systems</summary>
|
|
41
|
+
<div class="tc-details-body">
|
|
42
|
+
<section class="tc-panel">
|
|
43
|
+
<div class="tc-panel-head">
|
|
44
|
+
<span class="tc-eyebrow">Harness model</span>
|
|
45
|
+
<h2>Guardrails and Improvement sit under the harness</h2>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="tc-harness-system-grid">
|
|
48
|
+
{% for system in topology.systems %}
|
|
49
|
+
<section class="tc-harness-system tc-harness-system--{{ system.key }}">
|
|
50
|
+
<div>
|
|
51
|
+
<strong>{{ system.label }}</strong>
|
|
52
|
+
<span>{{ system.summary }}</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="tc-harness-list">
|
|
55
|
+
{% for item in system.items %}
|
|
56
|
+
<div><strong>{{ item.label }}</strong><span>{{ item.summary }}</span></div>
|
|
57
|
+
{% endfor %}
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
{% endfor %}
|
|
61
|
+
</div>
|
|
62
|
+
</section>
|
|
63
|
+
|
|
64
|
+
<section class="tc-panel">
|
|
65
|
+
<div class="tc-panel-head">
|
|
66
|
+
<span class="tc-eyebrow">Maintenance map</span>
|
|
67
|
+
<h2>Components are the implementation units</h2>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="tc-record-list">
|
|
70
|
+
{% for component in topology.components %}
|
|
71
|
+
<article class="tc-record-row">
|
|
72
|
+
<div class="tc-chip-list">
|
|
73
|
+
<span class="tc-pill tc-pill--neutral">{{ component.status }}</span>
|
|
74
|
+
{% for tag in component.tags %}
|
|
75
|
+
<span class="tc-chip">{{ tag }}</span>
|
|
76
|
+
{% endfor %}
|
|
77
|
+
</div>
|
|
78
|
+
<strong>{{ component.label }}</strong>
|
|
79
|
+
<small>{{ component.summary }}</small>
|
|
80
|
+
<small><code>{{ component.id }}</code>{% if component.depends_on %} depends on {{ component.depends_on|join:", " }}{% endif %}</small>
|
|
81
|
+
</article>
|
|
82
|
+
{% endfor %}
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
</div>
|
|
86
|
+
</details>
|
|
87
|
+
{% endblock %}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
{% extends "web/base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}MCP Router | tcx{% endblock %}
|
|
4
|
+
{% block page_label %}MCP Router{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<div
|
|
8
|
+
class="tc-mcp-page"
|
|
9
|
+
x-data="{
|
|
10
|
+
routerModalOpen: false,
|
|
11
|
+
selectedRouter: '{% if external_tools %}{{ external_tools.0.router.name|escapejs }}{% elif routers %}{{ routers.0.name|escapejs }}{% endif %}',
|
|
12
|
+
selectedTool: '{% if external_tools %}tool-{{ external_tools.0.id }}{% endif %}'
|
|
13
|
+
}"
|
|
14
|
+
@keydown.escape.window="routerModalOpen = false"
|
|
15
|
+
>
|
|
16
|
+
<section class="tc-mcp-toolbar" aria-label="MCP Router controls">
|
|
17
|
+
<div class="tc-mcp-toolbar-main">
|
|
18
|
+
<strong>Routers</strong>
|
|
19
|
+
<span>{{ router_count }} routes / {{ external_tool_count }} tools / {{ enabled_external_tool_count }} enabled</span>
|
|
20
|
+
</div>
|
|
21
|
+
<button class="tc-button tc-button-primary" type="button" @click="routerModalOpen = true">Add MCP</button>
|
|
22
|
+
</section>
|
|
23
|
+
|
|
24
|
+
<section class="tc-mcp-workbench" aria-label="MCP routing workflow">
|
|
25
|
+
<aside class="tc-mcp-column tc-mcp-column--routers">
|
|
26
|
+
<div class="tc-mcp-column-head">
|
|
27
|
+
<div>
|
|
28
|
+
<span class="tc-eyebrow">MCP list</span>
|
|
29
|
+
<h2>Route sources</h2>
|
|
30
|
+
</div>
|
|
31
|
+
<span class="tc-pill tc-pill--warn">{{ review_required_count }} review</span>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="tc-mcp-list">
|
|
35
|
+
{% for router in routers %}
|
|
36
|
+
<article class="tc-mcp-router-card" :class="{ 'is-active': selectedRouter === '{{ router.name|escapejs }}' }">
|
|
37
|
+
<button
|
|
38
|
+
class="tc-mcp-router-select"
|
|
39
|
+
type="button"
|
|
40
|
+
@click="selectedRouter = '{{ router.name|escapejs }}'; selectedTool = ''"
|
|
41
|
+
>
|
|
42
|
+
<span class="tc-pill tc-pill--{% if router.enabled %}good{% else %}neutral{% endif %}">{% if router.enabled %}enabled{% else %}disabled{% endif %}</span>
|
|
43
|
+
<strong>{{ router.label|default:router.name }}</strong>
|
|
44
|
+
<small>{{ router.transport }} / {{ router.trust_level }} / {{ router.last_status }}</small>
|
|
45
|
+
<code>{% if router.url %}{{ router.url }}{% else %}{{ router.command|default:"no command" }}{% endif %}</code>
|
|
46
|
+
</button>
|
|
47
|
+
|
|
48
|
+
<details class="tc-mcp-import">
|
|
49
|
+
<summary>Import tools/list</summary>
|
|
50
|
+
<form class="tc-form" method="post" action="{% url 'web-mcp-router-import' router.id %}">
|
|
51
|
+
{% csrf_token %}
|
|
52
|
+
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
|
53
|
+
<label>Discovery JSON
|
|
54
|
+
<textarea name="discovery_payload" rows="5" placeholder='{"tools":[{"name":"get_quote","description":"Get market quote","inputSchema":{"type":"object"}}]}'></textarea>
|
|
55
|
+
</label>
|
|
56
|
+
<button class="tc-mini-button" type="submit">Import</button>
|
|
57
|
+
</form>
|
|
58
|
+
</details>
|
|
59
|
+
</article>
|
|
60
|
+
{% empty %}
|
|
61
|
+
<div class="tc-empty-state">
|
|
62
|
+
<strong>No MCP routes</strong>
|
|
63
|
+
<span>Add a managed MCP route before importing tools.</span>
|
|
64
|
+
</div>
|
|
65
|
+
{% endfor %}
|
|
66
|
+
</div>
|
|
67
|
+
</aside>
|
|
68
|
+
|
|
69
|
+
<section class="tc-mcp-column tc-mcp-column--tools">
|
|
70
|
+
<div class="tc-mcp-column-head">
|
|
71
|
+
<div>
|
|
72
|
+
<span class="tc-eyebrow">Tool list</span>
|
|
73
|
+
<h2>Discovered tools</h2>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class="tc-mcp-list">
|
|
78
|
+
{% for tool in external_tools %}
|
|
79
|
+
<button
|
|
80
|
+
id="tool-{{ tool.id }}"
|
|
81
|
+
class="tc-mcp-tool-card"
|
|
82
|
+
type="button"
|
|
83
|
+
x-show="!selectedRouter || selectedRouter === '{{ tool.router.name|escapejs }}'"
|
|
84
|
+
:class="{ 'is-active': selectedTool === 'tool-{{ tool.id }}' }"
|
|
85
|
+
@click="selectedTool = 'tool-{{ tool.id }}'; selectedRouter = '{{ tool.router.name|escapejs }}'"
|
|
86
|
+
>
|
|
87
|
+
<span class="tc-pill tc-pill--{% if tool.risk_level == 'execution' or tool.risk_level == 'blocked' %}bad{% elif tool.risk_level == 'write' %}warn{% else %}neutral{% endif %}">{{ tool.risk_level }}</span>
|
|
88
|
+
<strong>{{ tool.external_name }}</strong>
|
|
89
|
+
<small>{{ tool.router.name }} / {{ tool.primitive }} / {{ tool.review_status }}</small>
|
|
90
|
+
<span class="tc-mcp-tool-meta">
|
|
91
|
+
<span>{{ tool.category }}</span>
|
|
92
|
+
<span>{{ tool.proxy_mode }}</span>
|
|
93
|
+
</span>
|
|
94
|
+
</button>
|
|
95
|
+
{% empty %}
|
|
96
|
+
<div class="tc-empty-state">
|
|
97
|
+
<strong>No tools yet</strong>
|
|
98
|
+
<span>Import discovery JSON from a route to classify tools.</span>
|
|
99
|
+
</div>
|
|
100
|
+
{% endfor %}
|
|
101
|
+
</div>
|
|
102
|
+
</section>
|
|
103
|
+
|
|
104
|
+
<section class="tc-mcp-column tc-mcp-column--handling">
|
|
105
|
+
<div class="tc-mcp-column-head">
|
|
106
|
+
<div>
|
|
107
|
+
<span class="tc-eyebrow">TradingCodex</span>
|
|
108
|
+
<h2>Processing</h2>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div class="tc-mcp-processing" x-show="!selectedTool">
|
|
113
|
+
<div class="tc-mcp-step">
|
|
114
|
+
<span>1</span>
|
|
115
|
+
<strong>Classify</strong>
|
|
116
|
+
<small>Unknown, secret, policy, and execution-like tools start blocked.</small>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="tc-mcp-step">
|
|
119
|
+
<span>2</span>
|
|
120
|
+
<strong>Map</strong>
|
|
121
|
+
<small>Allowed tools map to canonical capabilities and role scopes.</small>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="tc-mcp-step">
|
|
124
|
+
<span>3</span>
|
|
125
|
+
<strong>Dry-run</strong>
|
|
126
|
+
<small>Proxy decisions stay audited before any service adapter path is used.</small>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{% for tool in external_tools %}
|
|
131
|
+
<div class="tc-mcp-controls" x-show="selectedTool === 'tool-{{ tool.id }}'" x-cloak>
|
|
132
|
+
<div class="tc-mcp-selected-tool">
|
|
133
|
+
<div>
|
|
134
|
+
<span class="tc-eyebrow">Selected tool</span>
|
|
135
|
+
<h3>{{ tool.external_name }}</h3>
|
|
136
|
+
</div>
|
|
137
|
+
<span class="tc-pill tc-pill--{% if tool.enabled %}good{% else %}neutral{% endif %}">{% if tool.enabled %}enabled{% else %}disabled{% endif %}</span>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<form class="tc-mcp-control-card tc-form" method="post" action="{% url 'web-mcp-external-tool-update' tool.id %}">
|
|
141
|
+
{% csrf_token %}
|
|
142
|
+
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
|
143
|
+
<div class="tc-mcp-control-title">
|
|
144
|
+
<strong>Review policy</strong>
|
|
145
|
+
<small>{{ tool.router.name }} / {{ tool.review_status }}</small>
|
|
146
|
+
</div>
|
|
147
|
+
<label>Category
|
|
148
|
+
<select name="category">
|
|
149
|
+
{% for option in category_options %}<option value="{{ option }}" {% if tool.category == option %}selected{% endif %}>{{ option }}</option>{% endfor %}
|
|
150
|
+
</select>
|
|
151
|
+
</label>
|
|
152
|
+
<label>Risk
|
|
153
|
+
<select name="risk_level">
|
|
154
|
+
{% for option in risk_options %}<option value="{{ option }}" {% if tool.risk_level == option %}selected{% endif %}>{{ option }}</option>{% endfor %}
|
|
155
|
+
</select>
|
|
156
|
+
</label>
|
|
157
|
+
<label>Sensitivity
|
|
158
|
+
<select name="sensitivity">
|
|
159
|
+
{% for option in sensitivity_options %}<option value="{{ option }}" {% if tool.sensitivity == option %}selected{% endif %}>{{ option }}</option>{% endfor %}
|
|
160
|
+
</select>
|
|
161
|
+
</label>
|
|
162
|
+
<label>Capability <input name="canonical_capability" value="{{ tool.canonical_capability }}"></label>
|
|
163
|
+
<label>Proxy
|
|
164
|
+
<select name="proxy_mode">
|
|
165
|
+
{% for option in proxy_mode_options %}<option value="{{ option }}" {% if tool.proxy_mode == option %}selected{% endif %}>{{ option }}</option>{% endfor %}
|
|
166
|
+
</select>
|
|
167
|
+
</label>
|
|
168
|
+
<label>Roles <input name="allowed_roles" value="{{ tool.allowed_roles|join:", " }}"></label>
|
|
169
|
+
<label>Enabled
|
|
170
|
+
<select name="enabled">
|
|
171
|
+
<option value="false" {% if not tool.enabled %}selected{% endif %}>false</option>
|
|
172
|
+
<option value="true" {% if tool.enabled %}selected{% endif %}>true</option>
|
|
173
|
+
</select>
|
|
174
|
+
</label>
|
|
175
|
+
<button class="tc-button" type="submit">Save review</button>
|
|
176
|
+
</form>
|
|
177
|
+
|
|
178
|
+
<form class="tc-mcp-control-card tc-form" method="post" action="{% url 'web-mcp-external-tool-check' tool.id %}">
|
|
179
|
+
{% csrf_token %}
|
|
180
|
+
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
|
181
|
+
<div class="tc-mcp-control-title">
|
|
182
|
+
<strong>Proxy dry-run</strong>
|
|
183
|
+
<small>{{ tool.proxy_mode }} / {{ tool.canonical_capability }}</small>
|
|
184
|
+
</div>
|
|
185
|
+
<label>Principal <input name="principal_id" value="head-manager"></label>
|
|
186
|
+
<label>Arguments <textarea name="arguments" rows="4">{}</textarea></label>
|
|
187
|
+
<button class="tc-button" type="submit">Run check</button>
|
|
188
|
+
</form>
|
|
189
|
+
</div>
|
|
190
|
+
{% endfor %}
|
|
191
|
+
|
|
192
|
+
<section class="tc-mcp-audit" aria-label="Recent proxy decisions">
|
|
193
|
+
<div class="tc-mcp-control-title">
|
|
194
|
+
<strong>Recent decisions</strong>
|
|
195
|
+
<small>Audit trail</small>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="tc-mini-feed">
|
|
198
|
+
{% for call in recent_external_calls %}
|
|
199
|
+
<div>
|
|
200
|
+
<span class="tc-pill tc-pill--{% if call.decision == 'allow' %}good{% else %}bad{% endif %}">{{ call.decision }}</span>
|
|
201
|
+
<strong>{{ call.router_name }} / {{ call.external_name }}</strong>
|
|
202
|
+
<span>{{ call.principal_id }} / {{ call.proxy_mode }}</span>
|
|
203
|
+
</div>
|
|
204
|
+
{% empty %}
|
|
205
|
+
<p class="tc-empty">No proxy decisions yet.</p>
|
|
206
|
+
{% endfor %}
|
|
207
|
+
</div>
|
|
208
|
+
</section>
|
|
209
|
+
</section>
|
|
210
|
+
</section>
|
|
211
|
+
|
|
212
|
+
<div class="tc-modal-backdrop" x-show="routerModalOpen" x-cloak @click.self="routerModalOpen = false">
|
|
213
|
+
<section class="tc-modal" role="dialog" aria-modal="true" aria-labelledby="mcp-router-modal-title">
|
|
214
|
+
<div class="tc-modal-head">
|
|
215
|
+
<div>
|
|
216
|
+
<span class="tc-eyebrow">New route</span>
|
|
217
|
+
<h2 id="mcp-router-modal-title">Add MCP</h2>
|
|
218
|
+
</div>
|
|
219
|
+
<button class="tc-icon-button" type="button" aria-label="Close" @click="routerModalOpen = false">×</button>
|
|
220
|
+
</div>
|
|
221
|
+
<form class="tc-form" method="post" action="{% url 'web-mcp-router-create' %}">
|
|
222
|
+
{% csrf_token %}
|
|
223
|
+
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
|
224
|
+
<label>Name <input name="name" placeholder="alpaca-paper" required></label>
|
|
225
|
+
<label>Label <input name="label" placeholder="Alpaca Paper"></label>
|
|
226
|
+
<label>Transport
|
|
227
|
+
<select name="transport">
|
|
228
|
+
<option value="stdio">stdio</option>
|
|
229
|
+
<option value="http">http</option>
|
|
230
|
+
<option value="sse">sse</option>
|
|
231
|
+
</select>
|
|
232
|
+
</label>
|
|
233
|
+
<label>Command <input name="command" placeholder="uvx broker-mcp"></label>
|
|
234
|
+
<label>URL <input name="url" placeholder="https://localhost:9000/mcp"></label>
|
|
235
|
+
<label>Credential ref <input name="credential_ref" placeholder="os-keychain://tradingcodex/broker/default"></label>
|
|
236
|
+
<label>Enabled
|
|
237
|
+
<select name="enabled">
|
|
238
|
+
<option value="false">false</option>
|
|
239
|
+
<option value="true">true</option>
|
|
240
|
+
</select>
|
|
241
|
+
</label>
|
|
242
|
+
<div class="tc-modal-actions">
|
|
243
|
+
<button class="tc-button" type="button" @click="routerModalOpen = false">Cancel</button>
|
|
244
|
+
<button class="tc-button tc-button-primary" type="submit">Save router</button>
|
|
245
|
+
</div>
|
|
246
|
+
</form>
|
|
247
|
+
</section>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
{% endblock %}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{% extends "web/base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Orders | tcx{% endblock %}
|
|
4
|
+
{% block page_label %}Orders{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<section class="tc-section-grid tc-section-grid--three">
|
|
8
|
+
<article class="tc-summary-card"><span>Order intents</span><strong>{{ order_count }}</strong></article>
|
|
9
|
+
<article class="tc-summary-card"><span>Approvals</span><strong>{{ approval_count }}</strong></article>
|
|
10
|
+
<article class="tc-summary-card"><span>Executions</span><strong>{{ execution_count }}</strong></article>
|
|
11
|
+
</section>
|
|
12
|
+
|
|
13
|
+
<section class="tc-section-grid">
|
|
14
|
+
<article class="tc-panel">
|
|
15
|
+
<div class="tc-panel-head">
|
|
16
|
+
<span class="tc-eyebrow">Drafts</span>
|
|
17
|
+
<h2>Recent order intents</h2>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="tc-record-list">
|
|
20
|
+
{% for order in order_intents %}
|
|
21
|
+
<div class="tc-record-row">
|
|
22
|
+
<strong>{{ order.intent_id }}</strong>
|
|
23
|
+
<span>{{ order.side }} {{ order.quantity }} {{ order.symbol }} via {{ order.broker }}</span>
|
|
24
|
+
<small>{{ order.created_by }} · {{ order.created_at|date:"Y-m-d H:i" }}</small>
|
|
25
|
+
</div>
|
|
26
|
+
{% empty %}
|
|
27
|
+
<p class="tc-empty">No order intents are stored yet.</p>
|
|
28
|
+
{% endfor %}
|
|
29
|
+
</div>
|
|
30
|
+
</article>
|
|
31
|
+
|
|
32
|
+
<aside class="tc-panel">
|
|
33
|
+
<div class="tc-panel-head">
|
|
34
|
+
<span class="tc-eyebrow">Approvals</span>
|
|
35
|
+
<h2>Recent receipts</h2>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="tc-record-list">
|
|
38
|
+
{% for approval in approval_receipts %}
|
|
39
|
+
<div class="tc-record-row">
|
|
40
|
+
<strong>{{ approval.receipt_id }}</strong>
|
|
41
|
+
<span>{{ approval.order_intent_id }} · approved by {{ approval.approved_by }}</span>
|
|
42
|
+
<small>expires {{ approval.expires_at|date:"Y-m-d H:i" }}</small>
|
|
43
|
+
</div>
|
|
44
|
+
{% empty %}
|
|
45
|
+
<p class="tc-empty">No approval receipts are stored yet.</p>
|
|
46
|
+
{% endfor %}
|
|
47
|
+
</div>
|
|
48
|
+
</aside>
|
|
49
|
+
</section>
|
|
50
|
+
|
|
51
|
+
<section class="tc-panel">
|
|
52
|
+
<div class="tc-panel-head">
|
|
53
|
+
<span class="tc-eyebrow">Experimental execution ledger</span>
|
|
54
|
+
<h2>Recent results</h2>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="tc-record-list tc-record-list--grid">
|
|
57
|
+
{% for execution in execution_results %}
|
|
58
|
+
<div class="tc-record-row">
|
|
59
|
+
<strong>{{ execution.order_intent_id }}</strong>
|
|
60
|
+
<span>{{ execution.status }} via {{ execution.adapter }}</span>
|
|
61
|
+
<small>{{ execution.created_at|date:"Y-m-d H:i" }}</small>
|
|
62
|
+
</div>
|
|
63
|
+
{% empty %}
|
|
64
|
+
<p class="tc-empty">No execution results are stored yet.</p>
|
|
65
|
+
{% endfor %}
|
|
66
|
+
</div>
|
|
67
|
+
</section>
|
|
68
|
+
{% endblock %}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{% extends "web/base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Policy | tcx{% endblock %}
|
|
4
|
+
{% block page_label %}Policy{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<section class="tc-section-grid">
|
|
8
|
+
<article class="tc-panel">
|
|
9
|
+
<div class="tc-panel-head">
|
|
10
|
+
<span class="tc-eyebrow">Restricted list</span>
|
|
11
|
+
<h2>{{ policy.restricted_symbols|length }} symbols</h2>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="tc-record-list">
|
|
14
|
+
{% for item in policy.restricted_symbols %}
|
|
15
|
+
<div class="tc-record-row">
|
|
16
|
+
<strong>{{ item.symbol }}</strong>
|
|
17
|
+
<span>{{ item.reason|default:"No reason recorded" }}</span>
|
|
18
|
+
<small>{% if item.active %}active{% else %}inactive{% endif %}</small>
|
|
19
|
+
</div>
|
|
20
|
+
{% empty %}
|
|
21
|
+
<p class="tc-empty">No restricted symbols are active.</p>
|
|
22
|
+
{% endfor %}
|
|
23
|
+
</div>
|
|
24
|
+
</article>
|
|
25
|
+
|
|
26
|
+
<aside class="tc-panel">
|
|
27
|
+
<div class="tc-panel-head">
|
|
28
|
+
<span class="tc-eyebrow">Guardrail</span>
|
|
29
|
+
<h2>Policy posture</h2>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="tc-alert tc-alert-destructive">
|
|
32
|
+
<strong>{{ policy.explicit_denies|length }} explicit denies</strong>
|
|
33
|
+
<span>Risky policy changes stay outside the web review surface.</span>
|
|
34
|
+
</div>
|
|
35
|
+
</aside>
|
|
36
|
+
</section>
|
|
37
|
+
|
|
38
|
+
<section class="tc-panel">
|
|
39
|
+
<div class="tc-panel-head">
|
|
40
|
+
<span class="tc-eyebrow">Policy decisions</span>
|
|
41
|
+
<h2>Recent checks</h2>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="tc-table-wrap">
|
|
44
|
+
<table class="tc-data-table">
|
|
45
|
+
<thead>
|
|
46
|
+
<tr>
|
|
47
|
+
<th>Decision</th>
|
|
48
|
+
<th>Principal</th>
|
|
49
|
+
<th>Action</th>
|
|
50
|
+
<th>Resource</th>
|
|
51
|
+
<th>Created</th>
|
|
52
|
+
</tr>
|
|
53
|
+
</thead>
|
|
54
|
+
<tbody>
|
|
55
|
+
{% for decision in policy.recent_decisions %}
|
|
56
|
+
<tr>
|
|
57
|
+
<td><span class="tc-pill tc-pill--{{ decision.status_class }}">{{ decision.decision }}</span></td>
|
|
58
|
+
<td>{{ decision.principal_id }}</td>
|
|
59
|
+
<td>{{ decision.action }}</td>
|
|
60
|
+
<td>{{ decision.resource|default:"-" }}</td>
|
|
61
|
+
<td>{{ decision.created_at|date:"Y-m-d H:i" }}</td>
|
|
62
|
+
</tr>
|
|
63
|
+
{% empty %}
|
|
64
|
+
<tr><td colspan="5">No policy decisions have been recorded yet.</td></tr>
|
|
65
|
+
{% endfor %}
|
|
66
|
+
</tbody>
|
|
67
|
+
</table>
|
|
68
|
+
</div>
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
<details class="tc-details tc-diagnostics">
|
|
72
|
+
<summary>Explicit denies</summary>
|
|
73
|
+
<div class="tc-details-body">
|
|
74
|
+
<div class="tc-chip-list">
|
|
75
|
+
{% for action in policy.explicit_denies %}
|
|
76
|
+
<span class="tc-chip tc-chip-danger">{{ action }}</span>
|
|
77
|
+
{% endfor %}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</details>
|
|
81
|
+
{% endblock %}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{% extends "web/base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Portfolio | tcx{% endblock %}
|
|
4
|
+
{% block page_label %}Portfolio{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block content %}
|
|
7
|
+
<section class="tc-section-grid tc-section-grid--three">
|
|
8
|
+
<article class="tc-summary-card">
|
|
9
|
+
<span>Cash</span>
|
|
10
|
+
<strong>KRW {{ portfolio.cash_krw }}</strong>
|
|
11
|
+
</article>
|
|
12
|
+
<article class="tc-summary-card">
|
|
13
|
+
<span>Positions</span>
|
|
14
|
+
<strong>{{ portfolio.positions_count }}</strong>
|
|
15
|
+
</article>
|
|
16
|
+
<article class="tc-summary-card">
|
|
17
|
+
<span>Strategy</span>
|
|
18
|
+
<strong>{{ portfolio.strategy_id }}</strong>
|
|
19
|
+
</article>
|
|
20
|
+
</section>
|
|
21
|
+
|
|
22
|
+
<section class="tc-panel">
|
|
23
|
+
<div class="tc-panel-head">
|
|
24
|
+
<span class="tc-eyebrow">Holdings</span>
|
|
25
|
+
<h2>{{ portfolio.portfolio_id }} / {{ portfolio.account_id }}</h2>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="tc-table-wrap">
|
|
28
|
+
<table class="tc-data-table">
|
|
29
|
+
<thead>
|
|
30
|
+
<tr>
|
|
31
|
+
<th>Symbol</th>
|
|
32
|
+
<th>Quantity</th>
|
|
33
|
+
<th>Average price</th>
|
|
34
|
+
<th>Currency</th>
|
|
35
|
+
</tr>
|
|
36
|
+
</thead>
|
|
37
|
+
<tbody>
|
|
38
|
+
{% for position in portfolio.positions %}
|
|
39
|
+
<tr>
|
|
40
|
+
<td><strong>{{ position.symbol }}</strong></td>
|
|
41
|
+
<td>{{ position.quantity }}</td>
|
|
42
|
+
<td>{{ position.average_price }}</td>
|
|
43
|
+
<td>{{ position.currency }}</td>
|
|
44
|
+
</tr>
|
|
45
|
+
{% empty %}
|
|
46
|
+
<tr><td colspan="4">No positions are recorded in the central paper portfolio.</td></tr>
|
|
47
|
+
{% endfor %}
|
|
48
|
+
</tbody>
|
|
49
|
+
</table>
|
|
50
|
+
</div>
|
|
51
|
+
</section>
|
|
52
|
+
{% endblock %}
|