Sync: add infrastructure as code notes

This commit is contained in:
2026-04-24 19:58:02 +08:00
parent cc23df1883
commit e4f6f463cb
29 changed files with 2344 additions and 155 deletions

View File

@@ -499,6 +499,247 @@
<mxCell id="e-prop-folder-lbl" connectable="0" parent="e-prop-folder" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#fb923c;" value="property_id" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- ═══════════════════════════════════════════════════════════════
PUBLIC SCHEMA SWIMLANE平台运营层
Color: slate-900 bg / cyan-400 accent (#0f172a / #22d3ee variant: #7dd3fc)
Positioned ABOVE existing content at y=-1160
════════════════════════════════════════════════════════════════ -->
<mxCell id="region-public" parent="1"
style="swimlane;startSize=36;fillColor=#0c1a2e;strokeColor=#7dd3fc;fontColor=#7dd3fc;fontSize=13;fontStyle=1;swimlaneLine=1;rounded=1;arcSize=2;"
value="PUBLIC SCHEMA平台运营层" vertex="1">
<mxGeometry height="560" width="3400" x="-860" y="-1200" as="geometry" />
</mxCell>
<!-- ── 1. tenants ── -->
<mxCell id="pub-tenants" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.tenants&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;schema_name: varchar(63) [UNIQUE, immutable]&#xa;name: varchar(255)&#xa;short_name: varchar(100)&#xa;contact_name / contact_email&#xa;region: varchar(100)&#xa;plan: basic/professional/enterprise&#xa;status: creating/active/suspended/&#xa; pending_delete/deleted/failed&#xa;suspended_until: timestamptz&#xa;suspended_reason: varchar(50)&#xa;deleted_at: timestamptz&#xa;paid_until: date&#xa;on_trial: bool&#xa;is_canary: bool&#xa;created_at / updated_at: timestamptz&#xa;created_by: uuid&#xa;extra: jsonb" vertex="1">
<mxGeometry height="310" width="290" x="30" y="50" as="geometry" />
</mxCell>
<!-- ── 2. domains ── -->
<mxCell id="pub-domains" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.domains&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK tenant_id → tenants&#xa;domain: varchar(253) [UNIQUE]&#xa;is_primary: bool [UNIQUE partial]&#xa;created_at: timestamptz&#xa;⚠ domain 创建后不可修改" vertex="1">
<mxGeometry height="135" width="250" x="340" y="50" as="geometry" />
</mxCell>
<!-- ── 3. tenant_status_logs ── -->
<mxCell id="pub-tenant-status-logs" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.tenant_status_logs&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK tenant_id → tenants&#xa;from_status: varchar(20) [NULL=初始]&#xa;to_status: varchar(20)&#xa;reason: text&#xa;operator_id: uuid [NULL=Celery]&#xa;operator_name: varchar(100) [快照]&#xa;created_at: timestamptz&#xa;⚠ append-only — NO UPDATE/DELETE" vertex="1">
<mxGeometry height="175" width="270" x="340" y="200" as="geometry" />
</mxCell>
<!-- ── 4. platform_admins ── -->
<mxCell id="pub-admins" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.platform_admins&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;username: varchar(150) [UNIQUE]&#xa;email: varchar(254) [UNIQUE]&#xa;display_name: varchar(100)&#xa;password_hash: varchar(255)&#xa;role: super_admin/ops_operator/&#xa; read_only_auditor&#xa;is_active: bool&#xa;mfa_enabled: bool [TOTP 确认后→TRUE]&#xa;last_login_at: timestamptz&#xa;created_at / updated_at: timestamptz&#xa;🔗 FK created_by → platform_admins" vertex="1">
<mxGeometry height="225" width="270" x="640" y="50" as="geometry" />
</mxCell>
<!-- ── 5. admin_mfa_devices ── -->
<mxCell id="pub-mfa" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.admin_mfa_devices&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK admin_id → platform_admins&#xa;device_name: varchar(100)&#xa;totp_secret: varchar(255) [加密]&#xa;is_confirmed: bool&#xa;created_at: timestamptz&#xa;last_used_at: timestamptz" vertex="1">
<mxGeometry height="150" width="250" x="930" y="50" as="geometry" />
</mxCell>
<!-- ── 6. admin_sessions ── -->
<mxCell id="pub-sessions" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.admin_sessions&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK admin_id → platform_admins&#xa;session_token: varchar(255) [UNIQUE]&#xa;ip_address: inet&#xa;user_agent: text&#xa;is_active: bool&#xa;created_at: timestamptz&#xa;expires_at: timestamptz [30min rolling]&#xa;revoked_at: timestamptz&#xa;🔗 FK revoked_by → platform_admins" vertex="1">
<mxGeometry height="190" width="255" x="930" y="220" as="geometry" />
</mxCell>
<!-- ── 7. ip_whitelist ── -->
<mxCell id="pub-ip" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.ip_whitelist&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;cidr: cidr [如 203.0.113.0/24]&#xa;label: varchar(100)&#xa;is_active: bool&#xa;created_at: timestamptz&#xa;🔗 FK created_by → platform_admins" vertex="1">
<mxGeometry height="135" width="240" x="640" y="295" as="geometry" />
</mxCell>
<!-- ── 8. platform_audit_logs ── -->
<mxCell id="pub-audit" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.platform_audit_logs&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;operator_id: uuid [NULL=系统]&#xa;operator_name: varchar(100) [快照]&#xa;action_type: varchar(50)&#xa;target_type: varchar(30)&#xa;target_id / target_name: varchar&#xa;payload_summary: text&#xa;result: SUCCESS/FAILED&#xa;error_message: text&#xa;ip_address: inet&#xa;created_at: timestamptz&#xa;⚠ append-only — 建议月度 RANGE 分区" vertex="1">
<mxGeometry height="225" width="265" x="1210" y="50" as="geometry" />
</mxCell>
<!-- ── 9. backup_schedules ── -->
<mxCell id="pub-bk-schedules" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.backup_schedules&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK tenant_id → tenants [NULL=全局]&#xa;frequency: hourly/daily/weekly&#xa;scheduled_time: time [UTC]&#xa;retention_count: int&#xa;storage_target: local/s3/r2/gcs&#xa;is_active: bool&#xa;created_at / updated_at: timestamptz&#xa;🔗 FK created_by → platform_admins&#xa;UNIQUE(tenant_id)" vertex="1">
<mxGeometry height="195" width="265" x="1510" y="50" as="geometry" />
</mxCell>
<!-- ── 10. backup_records ── -->
<mxCell id="pub-bk-records" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.backup_records&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK tenant_id → tenants&#xa;trigger_type: auto/manual/&#xa; pre_upgrade/pre_restore&#xa;status: pending/in_progress/&#xa; success/failed&#xa;storage_target / storage_path: text&#xa;size_bytes: bigint&#xa;started_at / completed_at&#xa;error_message: text&#xa;🔗 FK triggered_by → platform_admins&#xa;upgrade_event_id: uuid&#xa;created_at: timestamptz" vertex="1">
<mxGeometry height="245" width="265" x="1510" y="270" as="geometry" />
</mxCell>
<!-- ── 11. export_tasks ── -->
<mxCell id="pub-exports" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.export_tasks&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK tenant_id → tenants&#xa;🔗 FK requested_by → platform_admins&#xa;modules: text[]&#xa;format: csv/json/sql_dump&#xa;status: pending/in_progress/done/failed&#xa;storage_path / download_url: text&#xa;expires_at: timestamptz [24h]&#xa;size_bytes: bigint&#xa;started_at / completed_at&#xa;created_at: timestamptz" vertex="1">
<mxGeometry height="215" width="265" x="1210" y="300" as="geometry" />
</mxCell>
<!-- ── 12. system_versions ── -->
<mxCell id="pub-versions" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.system_versions&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;version_number: varchar(50) [UNIQUE]&#xa;release_notes: text&#xa;artifact_url: text&#xa;status: current/previous/archived&#xa; [UNIQUE partial: status='current']&#xa;released_at: timestamptz&#xa;🔗 FK created_by → platform_admins" vertex="1">
<mxGeometry height="165" width="265" x="1810" y="50" as="geometry" />
</mxCell>
<!-- ── 13. upgrade_events ── -->
<mxCell id="pub-upgrades" parent="region-public"
style="text;html=1;strokeColor=#7dd3fc;fillColor=#0c1a2e;align=left;verticalAlign=top;spacingLeft=8;spacingTop=4;overflow=hidden;rotatable=0;fontSize=10;fontFamily=monospace;fontColor=#e2e8f0;whiteSpace=pre;"
value="&lt;b&gt;public.upgrade_events&lt;/b&gt;&#xa;&lt;hr/&gt;&#xa;🔑 PK id: uuid&#xa;🔗 FK from_version_id → system_versions&#xa;🔗 FK to_version_id → system_versions&#xa;event_type: upgrade/rollback&#xa;strategy: full/canary&#xa;status: pending/health_check/&#xa; in_progress/success/failed/rolled_back&#xa;tenant_progress: jsonb [{tenant,status,...}]&#xa;rollback_reason: text&#xa;incident_report: text&#xa;started_at / completed_at&#xa;🔗 FK initiated_by → platform_admins&#xa;created_at: timestamptz" vertex="1">
<mxGeometry height="255" width="280" x="1810" y="240" as="geometry" />
</mxCell>
<!-- ── Internal edges (PUBLIC schema) ── -->
<!-- tenants → domains -->
<mxCell id="pe-tenant-domain" edge="1" parent="region-public" source="pub-tenants" target="pub-domains"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="pe-tenant-domain-lbl" connectable="0" parent="pe-tenant-domain"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- tenants → tenant_status_logs -->
<mxCell id="pe-tenant-statuslog" edge="1" parent="region-public" source="pub-tenants" target="pub-tenant-status-logs"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="320" y="295" />
<mxPoint x="320" y="288" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-tenant-statuslog-lbl" connectable="0" parent="pe-tenant-statuslog"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N append-only" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- platform_admins → admin_mfa_devices -->
<mxCell id="pe-admin-mfa" edge="1" parent="region-public" source="pub-admins" target="pub-mfa"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="pe-admin-mfa-lbl" connectable="0" parent="pe-admin-mfa"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- platform_admins → admin_sessions -->
<mxCell id="pe-admin-session" edge="1" parent="region-public" source="pub-admins" target="pub-sessions"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="905" y="235" />
<mxPoint x="905" y="315" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-admin-session-lbl" connectable="0" parent="pe-admin-session"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- platform_admins → ip_whitelist (created_by) -->
<mxCell id="pe-admin-ip" edge="1" parent="region-public" source="pub-admins" target="pub-ip"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;dashed=1;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="755" y="280" />
<mxPoint x="755" y="363" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-admin-ip-lbl" connectable="0" parent="pe-admin-ip"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="created_by" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- tenants → backup_schedules -->
<mxCell id="pe-tenant-bksched" edge="1" parent="region-public" source="pub-tenants" target="pub-bk-schedules"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;dashed=1;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="320" y="430" />
<mxPoint x="1642" y="430" />
<mxPoint x="1642" y="248" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-tenant-bksched-lbl" connectable="0" parent="pe-tenant-bksched"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N (NULL=全局)" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- tenants → backup_records -->
<mxCell id="pe-tenant-bkrec" edge="1" parent="region-public" source="pub-tenants" target="pub-bk-records"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;dashed=1;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="320" y="480" />
<mxPoint x="1642" y="480" />
<mxPoint x="1642" y="395" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-tenant-bkrec-lbl" connectable="0" parent="pe-tenant-bkrec"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- tenants → export_tasks -->
<mxCell id="pe-tenant-export" edge="1" parent="region-public" source="pub-tenants" target="pub-exports"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;dashed=1;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="320" y="520" />
<mxPoint x="1342" y="520" />
<mxPoint x="1342" y="408" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-tenant-export-lbl" connectable="0" parent="pe-tenant-export"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="1:N" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- system_versions → upgrade_events (from/to) -->
<mxCell id="pe-ver-upgrade" edge="1" parent="region-public" source="pub-versions" target="pub-upgrades"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="pe-ver-upgrade-lbl" connectable="0" parent="pe-ver-upgrade"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="from/to version" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- upgrade_events → backup_records (upgrade_event_id) -->
<mxCell id="pe-upgrade-bkrec" edge="1" parent="region-public" source="pub-upgrades" target="pub-bk-records"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#7dd3fc;dashed=1;endArrow=ERmany;startArrow=ERone;fontSize=9;">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1808" y="392" />
<mxPoint x="1775" y="392" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pe-upgrade-bkrec-lbl" connectable="0" parent="pe-upgrade-bkrec"
style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;fontSize=9;fontColor=#7dd3fc;" value="upgrade_event_id" vertex="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>