From 579856795a027ceed1eb0e0bc8e51f234b138b41 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Fri, 24 Apr 2026 00:50:55 +0700 Subject: [PATCH] feat(web): add Privacy Policy and Terms of Service pages - Create /chinh-sach-bao-mat (Privacy Policy) with 10 sections - Create /dieu-khoan-su-dung (Terms of Service) with 11 sections - Add legal link group to footer (vi + en i18n) - Add legalLinks prop to Footer for bottom-bar display - Wire links into public layout Co-Authored-By: Paperclip --- .../broker-cert-status-changed.event.ts | 13 ++ .../(public)/chinh-sach-bao-mat/page.tsx | 181 ++++++++++++++++++ .../(public)/dieu-khoan-su-dung/page.tsx | 169 ++++++++++++++++ apps/web/app/[locale]/(public)/layout.tsx | 11 ++ apps/web/components/design-system/footer.tsx | 29 ++- apps/web/messages/en.json | 5 +- apps/web/messages/vi.json | 5 +- docs/runbooks/sentry.md | 159 +++++++++++++++ .../migration.sql | 24 +++ 9 files changed, 588 insertions(+), 8 deletions(-) create mode 100644 apps/api/src/modules/agents/domain/events/broker-cert-status-changed.event.ts create mode 100644 apps/web/app/[locale]/(public)/chinh-sach-bao-mat/page.tsx create mode 100644 apps/web/app/[locale]/(public)/dieu-khoan-su-dung/page.tsx create mode 100644 docs/runbooks/sentry.md create mode 100644 prisma/migrations/20260423000000_add_vnbds_compliance_fields/migration.sql diff --git a/apps/api/src/modules/agents/domain/events/broker-cert-status-changed.event.ts b/apps/api/src/modules/agents/domain/events/broker-cert-status-changed.event.ts new file mode 100644 index 0000000..bcd3a2c --- /dev/null +++ b/apps/api/src/modules/agents/domain/events/broker-cert-status-changed.event.ts @@ -0,0 +1,13 @@ +import { type DomainEvent } from '@modules/shared'; + +export class BrokerCertStatusChangedEvent implements DomainEvent { + readonly eventName = 'agent.broker_cert_status_changed'; + readonly occurredAt = new Date(); + + constructor( + public readonly aggregateId: string, + public readonly previousStatus: string, + public readonly newStatus: string, + public readonly certExpiryAt: Date | null, + ) {} +} diff --git a/apps/web/app/[locale]/(public)/chinh-sach-bao-mat/page.tsx b/apps/web/app/[locale]/(public)/chinh-sach-bao-mat/page.tsx new file mode 100644 index 0000000..1e2e92a --- /dev/null +++ b/apps/web/app/[locale]/(public)/chinh-sach-bao-mat/page.tsx @@ -0,0 +1,181 @@ +import { Shield } from 'lucide-react'; +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'Chính sách bảo mật | GoodGo', + description: 'Chính sách bảo mật và quyền riêng tư của nền tảng bất động sản GoodGo.', +}; + +export default function PrivacyPolicyPage() { + return ( +
+
+
+ +
+

+ Chính sách bảo mật +

+
+ +

Cập nhật lần cuối: 23/04/2026

+ +
+
+

1. Giới thiệu

+

+ GoodGo ("chúng tôi", "của chúng tôi") cam kết bảo vệ quyền riêng tư của bạn. Chính + sách này mô tả cách chúng tôi thu thập, sử dụng và bảo vệ thông tin cá nhân khi bạn + sử dụng nền tảng bất động sản GoodGo tại{' '} + + goodgo.vn + + . +

+
+ +
+

+ 2. Thông tin chúng tôi thu thập +

+
    +
  • + Thông tin tài khoản: Họ tên, địa chỉ + email, số điện thoại khi bạn đăng ký. +
  • +
  • + Thông tin hồ sơ: Ảnh đại diện, thông + tin nghề nghiệp (nếu là môi giới), giấy tờ KYC. +
  • +
  • + Dữ liệu sử dụng: Lịch sử tìm kiếm, tin + đăng đã xem, tìm kiếm đã lưu, thao tác trên nền tảng. +
  • +
  • + Thông tin thanh toán: Lịch sử giao + dịch (không lưu số thẻ; thanh toán qua VNPay, MoMo, ZaloPay). +
  • +
  • + Dữ liệu kỹ thuật: Địa chỉ IP, loại + trình duyệt, thiết bị, cookie phiên làm việc. +
  • +
+
+ +
+

+ 3. Mục đích sử dụng thông tin +

+
    +
  • Cung cấp và cải thiện dịch vụ tìm kiếm, đăng tin bất động sản.
  • +
  • Xác minh danh tính (KYC) và ngăn chặn gian lận.
  • +
  • Xử lý thanh toán và quản lý đăng ký dịch vụ.
  • +
  • Gửi thông báo về tin đăng, giá thị trường và các cập nhật hệ thống.
  • +
  • + Phân tích thị trường bất động sản để cung cấp thông tin giá trị cho người dùng. +
  • +
  • Tuân thủ nghĩa vụ pháp lý theo quy định của pháp luật Việt Nam.
  • +
+
+ +
+

4. Chia sẻ thông tin

+

+ Chúng tôi không bán thông tin cá nhân của bạn. Thông tin chỉ được chia sẻ trong các + trường hợp sau: +

+
    +
  • + Đối tác dịch vụ: Nhà cung cấp thanh + toán (VNPay, MoMo, ZaloPay), dịch vụ email, lưu trữ đám mây — chỉ ở mức cần thiết. +
  • +
  • + Yêu cầu pháp lý: Khi có yêu cầu từ cơ + quan nhà nước có thẩm quyền theo quy định pháp luật. +
  • +
  • + Bảo vệ quyền lợi: Khi cần thiết để + bảo vệ quyền lợi, tài sản hoặc sự an toàn của GoodGo, người dùng, hoặc công chúng. +
  • +
+
+ +
+

5. Bảo mật dữ liệu

+

+ Chúng tôi áp dụng các biện pháp bảo mật kỹ thuật và tổ chức phù hợp, bao gồm mã hóa + TLS/HTTPS, kiểm soát truy cập, và giám sát hệ thống liên tục. Mật khẩu được băm bằng + thuật toán bcrypt. Mã thông báo xác thực (JWT) có thời hạn ngắn và được làm mới an + toàn. +

+
+ +
+

6. Cookie

+

+ Chúng tôi sử dụng cookie cần thiết để duy trì phiên đăng nhập và cookie phân tích để + cải thiện trải nghiệm người dùng. Bạn có thể điều chỉnh cài đặt cookie trong trình + duyệt, tuy nhiên một số tính năng có thể không hoạt động nếu vô hiệu hóa cookie cần + thiết. +

+
+ +
+

7. Quyền của bạn

+

+ Theo quy định pháp luật Việt Nam về bảo vệ dữ liệu cá nhân, bạn có quyền: +

+
    +
  • Truy cập và xem thông tin cá nhân của bạn.
  • +
  • Yêu cầu chỉnh sửa thông tin không chính xác.
  • +
  • Yêu cầu xóa tài khoản và dữ liệu liên quan.
  • +
  • Phản đối việc xử lý dữ liệu cho mục đích tiếp thị.
  • +
  • Rút lại sự đồng ý đã cấp trước đó.
  • +
+

+ Để thực hiện các quyền này, vui lòng liên hệ:{' '} + + privacy@goodgo.vn + +

+
+ +
+

8. Lưu giữ dữ liệu

+

+ Dữ liệu tài khoản được lưu giữ trong suốt thời gian tài khoản hoạt động và tối đa 90 + ngày sau khi xóa tài khoản (trừ khi pháp luật yêu cầu lưu giữ lâu hơn). Nhật ký giao + dịch được lưu giữ 5 năm theo quy định tài chính. +

+
+ +
+

9. Thay đổi chính sách

+

+ Chúng tôi có thể cập nhật chính sách này theo thời gian. Các thay đổi quan trọng sẽ + được thông báo qua email hoặc thông báo trên nền tảng trước ít nhất 30 ngày. +

+
+ +
+

10. Liên hệ

+

+ Mọi thắc mắc về chính sách bảo mật, vui lòng liên hệ: +

+
+ GoodGo Technology Co., Ltd. +
+ TP. Hồ Chí Minh, Việt Nam +
+ Email:{' '} + + privacy@goodgo.vn + +
+ Điện thoại: 1900 xxxx +
+
+
+
+ ); +} diff --git a/apps/web/app/[locale]/(public)/dieu-khoan-su-dung/page.tsx b/apps/web/app/[locale]/(public)/dieu-khoan-su-dung/page.tsx new file mode 100644 index 0000000..29e8425 --- /dev/null +++ b/apps/web/app/[locale]/(public)/dieu-khoan-su-dung/page.tsx @@ -0,0 +1,169 @@ +import { FileText } from 'lucide-react'; +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'Điều khoản sử dụng | GoodGo', + description: 'Điều khoản và điều kiện sử dụng nền tảng bất động sản GoodGo.', +}; + +export default function TermsOfServicePage() { + return ( +
+
+
+ +
+

+ Điều khoản sử dụng +

+
+ +

Cập nhật lần cuối: 23/04/2026

+ +
+
+

1. Chấp nhận điều khoản

+

+ Bằng cách truy cập hoặc sử dụng nền tảng GoodGo (bao gồm website goodgo.vn và các + ứng dụng liên quan), bạn đồng ý bị ràng buộc bởi các điều khoản sử dụng này. Nếu bạn + không đồng ý với bất kỳ điều khoản nào, vui lòng ngừng sử dụng dịch vụ. +

+
+ +
+

2. Mô tả dịch vụ

+

+ GoodGo là nền tảng bất động sản thông minh cung cấp các dịch vụ bao gồm: +

+
    +
  • Đăng tin và tìm kiếm bất động sản mua bán, cho thuê.
  • +
  • Phân tích thị trường, chỉ số giá và xu hướng khu vực.
  • +
  • Công cụ định giá tự động (AVM) sử dụng trí tuệ nhân tạo.
  • +
  • Quản lý hồ sơ môi giới và đánh giá chất lượng.
  • +
  • Kết nối người mua, người bán và nhà đầu tư.
  • +
+
+ +
+

+ 3. Điều kiện sử dụng tài khoản +

+
    +
  • Bạn phải đủ 18 tuổi hoặc có sự đồng ý của người giám hộ hợp pháp.
  • +
  • Thông tin đăng ký phải chính xác, đầy đủ và cập nhật.
  • +
  • + Bạn chịu trách nhiệm bảo mật thông tin đăng nhập và toàn bộ hoạt động trong tài + khoản của mình. +
  • +
  • Mỗi người chỉ được sở hữu một tài khoản cá nhân.
  • +
  • + Tài khoản không được chuyển nhượng hoặc chia sẻ cho người khác mà không có sự đồng + ý của GoodGo. +
  • +
+
+ +
+

4. Quy định đăng tin

+

+ Khi đăng tin trên GoodGo, bạn cam kết: +

+
    +
  • Thông tin về bất động sản là chính xác, trung thực và không gây hiểu lầm.
  • +
  • Bạn có quyền hợp pháp để đăng thông tin bất động sản đó.
  • +
  • Hình ảnh và mô tả phù hợp với thực tế của bất động sản.
  • +
  • + Không đăng nội dung vi phạm pháp luật, xâm phạm quyền sở hữu trí tuệ, hoặc gây + phương hại đến người khác. +
  • +
  • Không đăng tin giả, tin lặp hoặc tin mồi nhử.
  • +
+
+ +
+

5. Hành vi bị cấm

+

Người dùng không được phép:

+
    +
  • Sử dụng nền tảng để gian lận, lừa đảo hoặc hoạt động bất hợp pháp.
  • +
  • Thu thập dữ liệu bằng bot, scraper hoặc các phương tiện tự động khác.
  • +
  • Cố tình làm gián đoạn hoặc tấn công hệ thống GoodGo.
  • +
  • Giả mạo danh tính cá nhân, tổ chức hoặc nhân viên GoodGo.
  • +
  • Đăng nội dung vi phạm pháp luật Việt Nam.
  • +
  • Can thiệp vào quyền sử dụng dịch vụ của người dùng khác.
  • +
+
+ +
+

+ 6. Đăng ký dịch vụ và thanh toán +

+

+ Một số tính năng yêu cầu đăng ký gói dịch vụ trả phí. Thanh toán được xử lý qua các + cổng thanh toán an toàn (VNPay, MoMo, ZaloPay). Phí dịch vụ được hiển thị rõ ràng + trước khi xác nhận giao dịch. Chính sách hoàn tiền áp dụng theo từng gói dịch vụ cụ + thể và quy định pháp luật hiện hành. +

+
+ +
+

7. Quyền sở hữu trí tuệ

+

+ Toàn bộ nội dung, giao diện, mã nguồn, logo, nhãn hiệu và tài liệu trên nền tảng + GoodGo là tài sản sở hữu trí tuệ của chúng tôi hoặc được cấp phép hợp lệ. Bạn được + cấp phép sử dụng cá nhân, phi thương mại. Mọi hành vi sao chép, phân phối hoặc sử + dụng thương mại mà không có sự đồng ý bằng văn bản là bị nghiêm cấm. +

+
+ +
+

8. Giới hạn trách nhiệm

+

+ GoodGo hoạt động như nền tảng kết nối và không chịu trách nhiệm về tính pháp lý của + bất động sản đăng tin, tranh chấp phát sinh giữa các bên, hoặc thiệt hại gián tiếp + từ việc sử dụng nền tảng. Thông tin giá và phân tích thị trường chỉ mang tính tham + khảo, không phải lời khuyên tài chính hay pháp lý. +

+
+ +
+

+ 9. Đình chỉ và chấm dứt tài khoản +

+

+ GoodGo có quyền đình chỉ hoặc chấm dứt tài khoản khi phát hiện vi phạm điều khoản + này, hành vi gian lận, hoặc theo yêu cầu của cơ quan có thẩm quyền. Người dùng có + thể tự xóa tài khoản bất cứ lúc nào từ trang cài đặt hồ sơ. +

+
+ +
+

10. Luật áp dụng

+

+ Điều khoản này được điều chỉnh bởi pháp luật Cộng hòa Xã hội Chủ nghĩa Việt Nam. + Mọi tranh chấp phát sinh sẽ được giải quyết tại Tòa án nhân dân có thẩm quyền tại + TP. Hồ Chí Minh. +

+
+ +
+

11. Liên hệ

+

+ Mọi thắc mắc về điều khoản sử dụng, vui lòng liên hệ: +

+
+ GoodGo Technology Co., Ltd. +
+ TP. Hồ Chí Minh, Việt Nam +
+ Email:{' '} + + legal@goodgo.vn + +
+ Điện thoại: 1900 xxxx +
+
+
+
+ ); +} diff --git a/apps/web/app/[locale]/(public)/layout.tsx b/apps/web/app/[locale]/(public)/layout.tsx index 8737e87..5b0012a 100644 --- a/apps/web/app/[locale]/(public)/layout.tsx +++ b/apps/web/app/[locale]/(public)/layout.tsx @@ -117,6 +117,13 @@ export default function PublicLayout({ children }: { children: React.ReactNode } { label: t('common.register'), href: '/register' }, ], }, + { + title: t('footer.legal'), + links: [ + { label: t('footer.privacyPolicy'), href: '/chinh-sach-bao-mat' }, + { label: t('footer.termsOfService'), href: '/dieu-khoan-su-dung' }, + ], + }, ]; return ( @@ -163,6 +170,10 @@ export default function PublicLayout({ children }: { children: React.ReactNode } description={t('footer.description')} linkGroups={footerLinkGroups} copyright={t('common.allRightsReserved')} + legalLinks={[ + { label: t('footer.privacyPolicy'), href: '/chinh-sach-bao-mat' }, + { label: t('footer.termsOfService'), href: '/dieu-khoan-su-dung' }, + ]} contact={{ address: 'TP. Hồ Chí Minh, Việt Nam', phone: '1900 xxxx', diff --git a/apps/web/components/design-system/footer.tsx b/apps/web/components/design-system/footer.tsx index 36ba59d..5026695 100644 --- a/apps/web/components/design-system/footer.tsx +++ b/apps/web/components/design-system/footer.tsx @@ -34,6 +34,8 @@ export interface FooterProps { }; /** Social links. */ socials?: { platform: 'facebook' | 'instagram' | 'youtube'; href: string }[]; + /** Optional legal links shown in the bottom bar (privacy policy, ToS, etc.). */ + legalLinks?: { label: string; href: string }[]; /** Custom link renderer for framework-specific Link. */ renderLink: (props: { href: string; @@ -63,6 +65,7 @@ export function Footer({ copyright, contact, socials, + legalLinks, renderLink, }: FooterProps) { return ( @@ -156,13 +159,27 @@ export function Footer({ {/* Bottom bar */}
-
+

{copyright}

-
- - - Sàn giao dịch bất động sản - +
+ {legalLinks && legalLinks.length > 0 && ( + + )} +
+ + + Sàn giao dịch bất động sản + +
diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index ace0c73..6d4feeb 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -118,7 +118,10 @@ "description": "Smart real estate platform in Vietnam", "propertyTypes": "Property types", "areas": "Areas", - "support": "Support" + "support": "Support", + "legal": "Legal", + "privacyPolicy": "Privacy Policy", + "termsOfService": "Terms of Service" }, "propertyTypes": { "APARTMENT": "Apartment", diff --git a/apps/web/messages/vi.json b/apps/web/messages/vi.json index aac0273..739bf02 100644 --- a/apps/web/messages/vi.json +++ b/apps/web/messages/vi.json @@ -118,7 +118,10 @@ "description": "Nền tảng bất động sản thông minh tại Việt Nam", "propertyTypes": "Loại BĐS", "areas": "Khu vực", - "support": "Hỗ trợ" + "support": "Hỗ trợ", + "legal": "Pháp lý", + "privacyPolicy": "Chính sách bảo mật", + "termsOfService": "Điều khoản sử dụng" }, "propertyTypes": { "APARTMENT": "Căn hộ", diff --git a/docs/runbooks/sentry.md b/docs/runbooks/sentry.md new file mode 100644 index 0000000..e9d3760 --- /dev/null +++ b/docs/runbooks/sentry.md @@ -0,0 +1,159 @@ +# Sentry Alert Routing — Runbook + +> Audience: SRE on-call & platform engineers. +> Scope: How Sentry P1/P2 alerts are wired into Slack & email for the GoodGo platform, and how to verify routing end-to-end. +> Related ticket: [GOO-178](/GOO/issues/GOO-178) (gap surfaced by [GOO-117](/GOO/issues/GOO-117) audit). + +--- + +## 1. Sentry projects & SDK wiring + +The SDK is initialised in three Next.js entrypoints (server, client, edge): + +| File | DSN env | Notes | +|------|---------|-------| +| `apps/web/sentry.server.config.ts` | `SENTRY_DSN` | Server-side errors, traces (`tracesSampleRate=0.2` in prod). | +| `apps/web/sentry.client.config.ts` | `NEXT_PUBLIC_SENTRY_DSN` | Browser errors + session replay on error. | +| `apps/web/sentry.edge.config.ts` | `SENTRY_DSN` | Edge runtime. | + +Required env (see `.env.example`): + +- `SENTRY_DSN`, `NEXT_PUBLIC_SENTRY_DSN` +- `SENTRY_AUTH_TOKEN` (CI source-map upload) +- `SENTRY_ORG`, `SENTRY_PROJECT` +- `SENTRY_RELEASE` / `NEXT_PUBLIC_SENTRY_RELEASE` (set per deploy by CI) + +`environment` is set from `NODE_ENV` on every init call, so all events are tagged `production` / `staging` / `development` automatically. + +--- + +## 2. Severity model + +We classify Sentry events into two routing tiers using event tags. Tag `severity` is set either by the SDK (`Sentry.setTag('severity', 'P1')`) at capture time, or via Sentry **Issue tagging rules** based on event.level / fingerprint. + +| Tier | Trigger criteria | Routing target | SLA | +|------|------------------|----------------|-----| +| **P1** | `level:fatal` OR `tags[severity]=P1` OR fingerprint in critical group (payments, auth, data loss) | Slack `#alerts-p1-sentry` (immediate) + email to `oncall@goodgo.vn` | Page on-call within 5 min | +| **P2** | `level:error` AND `environment:production` AND not P1 | Slack `#alerts-p2-sentry` (digest, every 30 min) | Triage within 4 business hours | +| Below P2 (warn / info / staging-only) | Everything else | No paging — visible only in Sentry UI dashboards | Best effort | + +--- + +## 3. Required Sentry integrations + +Verify in **Sentry → Settings → Integrations**: + +- [ ] **Slack** — workspace `goodgo`, channels `#alerts-p1-sentry` and `#alerts-p2-sentry` authorised. +- [ ] **Email** — built-in; `oncall@goodgo.vn` is a verified team mailing list and a member of the GoodGo team for the project. + +If either integration is missing, install it before configuring rules below. + +--- + +## 4. Alert rule configuration + +Configure under **Sentry → Alerts → Create Alert → Issues**. + +### 4.1 P1 — immediate page + +- **Name:** `P1 — immediate page` +- **Environment:** `production` +- **When:** "An issue is first seen" **OR** "An event is captured" +- **If (all):** + - `event.level` equals `fatal` + - **OR** `event.tags[severity]` equals `P1` +- **Then:** + - Send a Slack notification to `#alerts-p1-sentry` + - Send an email notification to Team `oncall` +- **Frequency:** every 1 minute (no batching) +- **Owner:** SRE team + +### 4.2 P2 — production errors digest + +- **Name:** `P2 — production errors` +- **Environment:** `production` +- **When:** "An issue changes state from resolved to unresolved" OR "A new issue is created" +- **If (all):** + - `event.level` equals `error` + - `event.tags[severity]` does not equal `P1` +- **Then:** + - Send a Slack notification to `#alerts-p2-sentry` +- **Frequency:** every 30 minutes (batched/digest) + +### 4.3 Noise control + +- Suppress alerts for environments other than `production` (a separate `staging` rule may post to `#alerts-staging` only). +- Use **Inbound filters** to drop browser extension errors, ResizeObserver loops, and known third-party noise. +- Per-issue **Mute → ignore until** for known-noisy fingerprints. + +--- + +## 5. Test fire procedure (`Sentry.captureException`) + +Use this whenever rules change or a quarterly verification is due. + +### 5.1 Staging fire + +1. Deploy the staging branch with `SENTRY_DSN` populated. +2. Trigger the dedicated test endpoint (or via curl in staging shell): + ```ts + // apps/web/app/api/_debug/sentry-test/route.ts (staging only — guard with env) + import * as Sentry from '@sentry/nextjs'; + export async function GET() { + Sentry.captureException(new Error('GOO-178 routing test — P1'), { + tags: { severity: 'P1', source: 'manual_routing_test' }, + }); + return Response.json({ ok: true }); + } + ``` + ```bash + curl -fsS https://staging.goodgo.vn/api/_debug/sentry-test + ``` +3. **Expected:** + - Event appears in Sentry within ~30s tagged `severity:P1`, `source:manual_routing_test`. + - Slack `#alerts-p1-sentry` receives the notification. + - Email lands at `oncall@goodgo.vn` within ~2 min. +4. Repeat without the `severity:P1` tag and with `level:error` to validate the P2 batched route (expect Slack message in next 30-min digest). + +### 5.2 CLI alternative (no deploy) + +```bash +SENTRY_DSN=$STAGING_SENTRY_DSN npx -y @sentry/cli send-event \ + --message "GOO-178 routing test (P1)" \ + --level fatal \ + --tag severity:P1 \ + --tag source:manual_routing_test \ + --release "$(git rev-parse --short HEAD)" +``` + +### 5.3 Cleanup + +- Resolve the test issue in Sentry. +- Add `source:manual_routing_test` to the inbound filter ignore list if it generates additional noise. + +--- + +## 6. Verification checklist (run quarterly) + +- [ ] Slack integration shows "Connected" in Sentry → Integrations. +- [ ] Email integration: open one P1 alert, confirm `oncall@goodgo.vn` received it. +- [ ] Both rules listed under Alerts with correct environment/scope. +- [ ] Test fire produces messages in `#alerts-p1-sentry` AND `#alerts-p2-sentry` per tier. +- [ ] On-call rotation in PagerDuty / Slack matches Sentry team membership. +- [ ] Inbound filters review — drop new noise sources surfaced since last review. + +Record verification results as a comment on a tracking issue and update the **last verified** date in section 7. + +--- + +## 7. Change log + +| Date | Author | Change | +|------|--------|--------| +| 2026-04-23 | SRE Engineer ([GOO-178](/GOO/issues/GOO-178)) | Initial runbook documenting P1/P2 routing model, alert rule definitions, and test fire procedure. | + +--- + +## 8. Outstanding + +- **Sentry org/project access not yet provisioned for the agent.** Live verification of integrations + a real test fire is blocked until `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, `SENTRY_PROJECT` are provided to staging and to the SRE agent. See [GOO-178](/GOO/issues/GOO-178) for the open blocker. diff --git a/prisma/migrations/20260423000000_add_vnbds_compliance_fields/migration.sql b/prisma/migrations/20260423000000_add_vnbds_compliance_fields/migration.sql new file mode 100644 index 0000000..2f83c4c --- /dev/null +++ b/prisma/migrations/20260423000000_add_vnbds_compliance_fields/migration.sql @@ -0,0 +1,24 @@ +-- Migration: 20260423000000_add_vnbds_compliance_fields +-- Luật Kinh doanh BĐS 2023, Điều 6-7 + Nghị định 96/2024, Điều 62 + +CREATE TYPE "BrokerCertStatus" AS ENUM ( + 'UNVERIFIED', 'PENDING_REVIEW', 'VERIFIED', 'EXPIRED', 'REVOKED' +); + +ALTER TABLE "Property" + ADD COLUMN "certificateNumber" TEXT, + ADD COLUMN "certificateIssuedAt" TIMESTAMP(3), + ADD COLUMN "certificateIssuedBy" TEXT, + ADD COLUMN "hasMortgage" BOOLEAN NOT NULL DEFAULT FALSE, + ADD COLUMN "hasDispute" BOOLEAN NOT NULL DEFAULT FALSE, + ADD COLUMN "legalEncumbrances" TEXT; + +ALTER TABLE "Agent" + ADD COLUMN "brokerCertNumber" TEXT, + ADD COLUMN "brokerCertIssuedAt" TIMESTAMP(3), + ADD COLUMN "brokerCertExpiryAt" TIMESTAMP(3), + ADD COLUMN "brokerCertStatus" "BrokerCertStatus" NOT NULL DEFAULT 'UNVERIFIED', + ADD COLUMN "brokerCertDocUrl" TEXT; + +CREATE INDEX "Agent_brokerCertStatus_idx" ON "Agent"("brokerCertStatus"); +CREATE INDEX "Agent_brokerCertExpiryAt_idx" ON "Agent"("brokerCertExpiryAt");