1مقدمه و دامنهٔ سند
این سند، مرجع فنیِ واحدِ تیم مهندسی برای طراحی، پیادهسازی و استقرار سامانهٔ «نگاهبان» است. هدف، تبدیل نیازمندیهای محصول به یک معماری اجراییِ دقیق و یک نقشهٔ راهِ ساختِ بخشبهبخش است.
مخاطب این سند، توسعهدهندگان Backend و موبایل، مهندسان هوش مصنوعی، DevOps و مسئول امنیت است. فرض بر آشنایی خواننده با معماری میکروسرویس، کانتینر، پایگاهدادهٔ رابطهای و مفاهیم بینایی ماشین است.
اصول طراحی حاکم بر پروژه
- امنیت پیشفرض (Secure by Default): رمزنگاری در حالت سکون و انتقال، کمینهٔ دسترسی، و ایزولاسیون شبکهٔ دوربینها از همان ابتدا.
- حاکمیت داده (Data Sovereignty): امکان استقرار کاملاً On-Prem بدون خروج هیچ بایتی از دادهٔ زیستسنجشی از محیط مشتری — الزام مراکز حساس.
- چندمستأجری و مقیاسپذیری (Multi-tenant & Scalable): یک هسته که از یک لابی تا یک کلاستر چندطبقه را با همان کد پوشش دهد.
- رخدادمحور (Event-Driven): هر ورود/خروج، هر fix مکانی و هر تطبیق چهره یک رخداد است که از طریق گذرگاه پیام جریان مییابد.
- مشاهدهپذیری کامل (Observability): هیچ سرویسی بدون log ساختیافته، metric و trace به Production نمیرود.
واژهنامهٔ کوتاه
| اصطلاح | توضیح |
|---|---|
RTLS | Real-Time Location System — سامانهٔ مکانیابی بلادرنگ داخلی |
Embedding | بردار عددی (۵۱۲ بُعدی) نمایندهٔ یک چهره برای تطبیق |
Geofence | محدودهٔ جغرافیایی/چندضلعی برای زون یا شعاع عملیاتی |
FAR / FRR | نرخ پذیرش غلط / نرخ رد غلط در احراز هویت زیستسنجشی |
Liveness | تشخیص زندهبودن چهره برای مقابله با جعل (عکس/ویدئو/ماسک) |
Tenant | یک مشتری/سازمان مجزا با دادهٔ ایزوله در سامانه |
2معماری کلان سیستم
نگاهبان از پنج لایهٔ منطقی تشکیل شده است: لایهٔ لبه (دوربین، اسکنر، تگ و گیتوی)، لایهٔ دریافت و دروازه، لایهٔ سرویسها (میکروسرویسها)، لایهٔ داده، و لایهٔ کلاینت (اپ موبایل و داشبورد). ارتباط درونسرویسی با gRPC و ارتباط بیرونی با REST/WebSocket است؛ رخدادها از طریق یک گذرگاه پیام (NATS/Kafka) منتشر میشوند.
جریانهای کلیدی داده
- ثبت حضور: اسکنر چهره/اثرانگشت ← Attendance Service ← اعتبارسنجی (زمان+مکان+liveness+تطبیق) ← رخداد
attendance.checked_in. - تشخیص چهرهٔ ورودی: دوربین (RTSP) ← Video Service (نمونهگیری فریم) ← Face Service (تشخیص←embedding←تطبیق با گالری) ← رخداد
face.detected/face.unauthorized← Alert Service. - مکانیابی نیرو: تگ ← گیتویها (RSSI/TWR) ← RTLS Service (فیلتر+مثلثبندی) ← fix مکانی ← Zone Service (تعیین زون/شعاع) ← Realtime Service (WebSocket به نقشه).
- تحلیل رفتار: fixهای مکانی + رخدادها ← Behavior Service (استخراج ویژگی per shift) ← مقایسه با baseline ← امتیاز ناهنجاری ← Alert در صورت تخطی.
3پشتهٔ فناوری و قراردادها
| لایه | فناوری | نسخهٔ پیشنهادی | علت انتخاب |
|---|---|---|---|
| Backend سرویسها | Go | 1.22+ | همروندی بالا، باینری سبک، مناسب سرویسهای بلادرنگ |
| AI / بینایی ماشین | Python + ONNX Runtime | 3.11 / 1.17 | اکوسیستم مدلها؛ اجرا با TensorRT/CUDA |
| اپ موبایل | Flutter | 3.22+ | یک کد، دو پلتفرم؛ دسترسی به دوربین/BLE/بیومتریک |
| داشبورد وب | React + TypeScript | 18 / 5 | اکوسیستم بالغ، نقشهٔ تعاملی، RBAC در UI |
| پایگاهداده | PostgreSQL | 16 + pgvector + TimescaleDB | رابطهای + بردار چهره + سریزمانی مکان |
| کش/حضور | Redis | 7+ | presence، geofence state، rate-limit، pub/sub |
| گذرگاه پیام | NATS JetStream | 2.10+ | سبک، تأخیر پایین (جایگزین Kafka در مقیاس کوچک) |
| پردازش ویدئو | GStreamer / FFmpeg | 1.24 / 6 | رمزگشایی سختافزاری (NVDEC)، نمونهگیری فریم |
| استقرار | Docker + Kubernetes | K8s 1.29+ | مقیاسپذیری، GPU scheduling، rollout |
| شیءذخیره | MinIO (S3 API) | — | آرشیو ویدئو/کلیپ رویداد، On-Prem |
قراردادهای مهندسی
- API بیرونی: REST/JSON با نسخهبندی مسیر (
/api/v1/...)، احراز هویتBearer JWT؛ خطاها با مدل یکنواخت ({code, message, traceId}). - API درونی: gRPC با Protobuf؛ احراز سرویسبهسرویس با mTLS.
- رخدادها: نامگذاری
domain.action(مثلaccess.denied)، payload نسخهدار، تحویل at-least-once و idempotency-key. - زمان: همهٔ مهرهای زمانی UTC و ISO-8601؛ ساعتِ مرجع، سرور است نه دستگاه.
- شناسهها:
UUIDv7(مرتبشدنی زمانی) برای کلیدهای اصلی. - پیکربندی: ۱۲-Factor؛ از طریق متغیر محیطی و Vault؛ هیچ رازی در ایمیج یا کد.
4مدل داده
مدل داده چندمستأجری است؛ هر ردیف دارای tenant_id برای ایزولاسیون است (با Row-Level Security در PostgreSQL). موجودیتهای اصلی و رابطهٔ آنها در زیر آمده، سپس DDL جداول کلیدی.
موجودیتهای اصلی
| موجودیت | شرح | روابط کلیدی |
|---|---|---|
tenant | سازمان/مشتری | ۱ به n با sites, persons |
site / building / floor | سلسلهمراتب مکان فیزیکی | floor دارای zones و cameras |
zone | ناحیهٔ چندضلعی روی یک طبقه با سطح دسترسی | n به n با roles (قواعد دسترسی) |
person | نگهبان/کارمند/بازدیدکننده | ۱ به n با face_templates، shifts |
device | اسکنر، تگ، گیتوی، دوربین | متعلق به floor/site |
face_template | بردار embedding چهره (رمزنگاریشده) | متعلق به person |
shift | شیفت کاری با پنجرهٔ زمانی و سایت | ۱ به n با attendance |
attendance_record | ثبت ورود/خروج زیستسنجشی | متعلق به person+shift |
location_fix | مختصات لحظهای نیرو (سریزمانی) | متعلق به person/tag |
access_event | ورود/خروج به زون (مجاز/غیرمجاز) | person × zone |
alert | هشدار تولیدشده | منبع: هر سرویس |
behavior_profile | امضای رفتاری پایهٔ هر نیرو | متعلق به person |
audit_log | گزارش ممیزی تغییرناپذیر | — |
DDL جداول کلیدی (PostgreSQL)
-- افزونهها
CREATE EXTENSION IF NOT EXISTS vector; -- pgvector
CREATE EXTENSION IF NOT EXISTS timescaledb;
-- اشخاص
CREATE TABLE person (
id UUID PRIMARY KEY DEFAULT uuidv7(),
tenant_id UUID NOT NULL,
full_name TEXT NOT NULL,
national_id TEXT,
role TEXT NOT NULL CHECK (role IN ('guard','employee','visitor','admin')),
status TEXT NOT NULL DEFAULT 'active',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON person (tenant_id, role);
-- قالب چهره: فقط embedding رمزنگاریشده نگهداری میشود، نه تصویر خام
CREATE TABLE face_template (
id UUID PRIMARY KEY DEFAULT uuidv7(),
tenant_id UUID NOT NULL,
person_id UUID NOT NULL REFERENCES person(id) ON DELETE CASCADE,
embedding vector(512) NOT NULL, -- L2-normalized
quality REAL NOT NULL, -- 0..1
enc_blob BYTEA, -- نسخهٔ رمزنگاریشدهٔ متادیتا (AES-256-GCM)
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ایندکس برداری برای جستوجوی نزدیکترین همسایه
CREATE INDEX ON face_template USING hnsw (embedding vector_cosine_ops);
-- زون: چندضلعی روی یک طبقه
CREATE TABLE zone (
id UUID PRIMARY KEY DEFAULT uuidv7(),
tenant_id UUID NOT NULL,
floor_id UUID NOT NULL,
name TEXT NOT NULL,
polygon JSONB NOT NULL, -- [[x,y],...] مختصات محلی طبقه
sensitivity SMALLINT NOT NULL DEFAULT 1 -- 1..5
);
-- قاعدهٔ دسترسی: نقش × زون × بازهٔ زمانی
CREATE TABLE access_rule (
id UUID PRIMARY KEY DEFAULT uuidv7(),
zone_id UUID NOT NULL REFERENCES zone(id),
role TEXT NOT NULL,
time_window JSONB, -- {days:[...], from:'08:00', to:'20:00'}
effect TEXT NOT NULL CHECK (effect IN ('allow','deny'))
);
-- fixهای مکانی بهصورت hypertable سریزمانی
CREATE TABLE location_fix (
ts TIMESTAMPTZ NOT NULL,
tenant_id UUID NOT NULL,
person_id UUID NOT NULL,
floor_id UUID NOT NULL,
x REAL NOT NULL,
y REAL NOT NULL,
accuracy_m REAL,
source TEXT NOT NULL -- 'uwb' | 'ble' | 'fused'
);
SELECT create_hypertable('location_fix','ts');
CREATE INDEX ON location_fix (person_id, ts DESC);
-- رخداد دسترسی
CREATE TABLE access_event (
id UUID PRIMARY KEY DEFAULT uuidv7(),
tenant_id UUID NOT NULL,
person_id UUID,
zone_id UUID NOT NULL,
decision TEXT NOT NULL, -- 'authorized' | 'unauthorized'
ts TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- گزارش ممیزی تغییرناپذیر (append-only، زنجیرهٔ هش)
CREATE TABLE audit_log (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
tenant_id UUID NOT NULL,
actor TEXT NOT NULL,
action TEXT NOT NULL,
target TEXT,
ts TIMESTAMPTZ NOT NULL DEFAULT now(),
prev_hash BYTEA,
row_hash BYTEA NOT NULL
);face_template در سطح ستون با کلید per-tenant از Vault رمزنگاری میشود.در Redis، ساختارهای زیر نگهداری میشوند: presence:{person_id} (آخرین وضعیت/زون با TTL)، geo:{person_id} (آخرین fix برای ارزیابی geofence)، و کانالهای pubsub: alerts, positions برای انتشار بلادرنگ.
5سرویسها (میکروسرویسها) — بخش به بخش
هر سرویس مستقل، صاحب دادهٔ خود و مستقل قابلاستقرار است. در ادامه برای هر سرویس: مسئولیت، API، الگوریتم/نکات پیادهسازی و گامهای ساخت آمده است.
۴٫۱ — Auth & API Gateway
نقطهٔ ورود واحد؛ مسئول احراز هویت، صدور/نوسازی JWT، نرخگذاری، مسیریابی و ترجمهٔ REST↔gRPC.
کنترل دسترسی ترکیبی RBAC + ABAC است: نقش پایه + ویژگیها (tenant، site، سطح حساسیت). ادعاهای JWT شامل sub, tenant, roles[], scopes[] است.
- تعریف مدل نقش/مجوز و seed نقشهای پایه (admin, operator, guard, viewer).
- پیادهسازی صدور JWT با امضای EdDSA و چرخش کلید (kid).
- Middleware اعتبارسنجی توکن + بررسی scope در Gateway.
- نرخگذاری per-IP و per-token با Redis (الگوریتم token-bucket).
- mTLS برای ارتباط Gateway با سرویسهای داخلی.
۴٫۲ — Personnel & Identity Service
مدیریت اشخاص، نقشها، شیفتها و فرایند ثبتنام چهره (enrollment).
۴٫۳ — Face Recognition Service
هستهٔ هوش مصنوعیِ تصویر. خط لولهٔ استنتاج: تشخیص چهره ← همترازی ← embedding ← liveness ← تطبیق با گالری ← تصمیم.
| مرحله | مدل/روش | خروجی | نکته |
|---|---|---|---|
| Detection | SCRFD / RetinaFace (ONNX) | bbox + ۵ لندمارک | اجرا روی GPU، batch فریمها |
| Alignment | تبدیل تشابهی به 112×112 | چهرهٔ همتراز | از ۵ لندمارک استاندارد |
| Embedding | ArcFace (glintr100) | بردار ۵۱۲ بُعدی L2-norm | FP16 با TensorRT |
| Liveness | MiniFASNet (anti-spoof) | امتیاز زندهبودن | رد عکس/ویدئو/ماسک |
| Matching | Cosine + pgvector HNSW | نزدیکترین + امتیاز | آستانهٔ کالیبرهشده |
تطبیق بر اساس شباهت کسینوسی است. آستانهٔ عملیاتی بر مبنای منحنی ROC و نقطهٔ کاری مطلوب (مثلاً FAR ≤ 1e-4) تعیین و per-deployment کالیبره میشود.
# شبهکد تطبیق
emb = embed(align(detect(frame))) # بردار 512، نرمالشده
if liveness_score(frame) < LIVENESS_TH:
return reject("spoof")
cand = pgvector_search(emb, gallery, k=1) # 1 <-> cosine distance
score = 1.0 - cand.distance # شباهت کسینوسی
if score >= MATCH_TH: # مثلاً 0.42 (کالیبرهشونده)
emit("face.detected", person=cand.id, score=score)
else:
emit("face.unauthorized", score=score)- آمادهسازی مدلها به ONNX و سپس TensorRT engine (FP16) برای GPU هدف.
- سرویس استنتاج با gRPC streaming؛ ورودی فریم، خروجی نتیجهٔ تطبیق.
- بارگذاری گالری embedding به pgvector + ساخت ایندکس HNSW.
- پیادهسازی liveness و motion gate برای کاهش بار.
- ابزار کالیبراسیون آستانه روی دادهٔ هر استقرار + گزارش FAR/FRR.
۴٫۴ — Video Ingestion & Stream Service
اتصال به دوربینها با ONVIF (کشف) و RTSP (جریان)، رمزگشایی سختافزاری، نمونهگیری فریم و تحویل به Face Service؛ و ضبط کلیپ کوتاه پیرامون هر رخداد مهم.
# نمونهٔ خط لولهٔ GStreamer با رمزگشایی NVDEC و نمونهگیری فریم gst-launch-1.0 rtspsrc location=rtsp://CAM/Streaming/Channels/101 latency=100 ! \ rtph264depay ! h264parse ! nvv4l2decoder ! \ videorate ! 'video/x-raw,framerate=5/1' ! appsink
- هر دوربین یک worker مستقل؛ پایش سلامت و reconnect خودکار.
- Motion gate برای فعالسازی استنتاج فقط هنگام حرکت → صرفهجویی GPU.
- ضبط حلقهای (ring buffer) برای داشتن ۱۰ ثانیه پیش از رخداد در کلیپ.
- آرشیو کلیپها در MinIO با سیاست ماندگاری قابلپیکربندی.
۴٫۵ — RTLS / Tag Location Service
محاسبهٔ موقعیت دقیق نیرو از سیگنال تگها. دو فناوری پشتیبانی میشود: UWB (دقت ۱۰ تا ۳۰ سانتیمتر، مبتنی بر TWR/TDoA) برای مراکز حساس، و BLE (دقت متری، مبتنی بر RSSI + فینگرپرینت) برای استقرار اقتصادی.
- هر طبقه دارای چند anchor/گیتوی با مختصات کالیبرهشده است.
- BLE: مدل افت مسیر (path-loss) برای فاصله + فیلتر کالمن برای صافسازی مسیر و حذف نوسان.
- UWB: Two-Way Ranging بین تگ و anchorها و سپس چندجانبهسازی (multilateration).
- تشخیص طبقه با تجمیع anchorهای پاسخدهنده (+ بارومتر تگ در صورت وجود).
- خروجی:
location_fixبا نرخ ۱ تا ۴ هرتز ← Timescale + Redis.
۴٫۶ — Zone & Access Control Service
ارزیابی هر fix مکانی نسبت به زونها و قواعد دسترسی، و تولید رخداد ورود مجاز/غیرمجاز و خروج از محدودهٔ عملیاتی.
// تعیین زون با الگوریتم point-in-polygon (ray casting)
func PointInPolygon(p Point, poly []Point) bool {
inside := false
j := len(poly) - 1
for i := 0; i < len(poly); i++ {
if (poly[i].Y > p.Y) != (poly[j].Y > p.Y) &&
p.X < (poly[j].X-poly[i].X)*(p.Y-poly[i].Y)/(poly[j].Y-poly[i].Y)+poly[i].X {
inside = !inside
}
j = i
}
return inside
}
// خط لولهٔ ارزیابی هر fix
func Evaluate(fix Fix) {
zone := resolveZone(fix) // کدام زون؟
if !withinOperationalRadius(fix) { // خارج از محدودهٔ مجاز؟
emit("guard.out_of_bounds", fix)
}
if zone != nil {
if !accessAllowed(fix.PersonRole, zone, fix.TS) {
emit("access.unauthorized", fix, zone) // ← Alert
} else {
emit("access.authorized", fix, zone)
}
}
}موتور قواعد بهصورت اعلانی (declarative) است: قواعد allow/deny بر حسب نقش × زون × بازهٔ زمانی ذخیره و بهترتیب اولویت ارزیابی میشوند (deny مقدم بر allow).
۴٫۷ — Attendance Service
ثبت ورود/خروج زیستسنجشی مقیّد به زمان و مکان. اعتبارسنجی سمت سرور است و به ساعت/موقعیت دستگاه اعتماد نمیشود.
- دستگاه/اپ، چهره و اثرانگشت + شناسهٔ دستگاه و موقعیت را ارسال میکند.
- سرور بررسی میکند: liveness پاس شده باشد، چهره با person تطبیق یابد، اثرانگشت تأیید شود.
- بررسی geofence: موقعیت در محدودهٔ سایتِ شیفت باشد.
- بررسی پنجرهٔ زمانی: زمان سرور در بازهٔ شیفت ± مهلت مجاز باشد.
- ثبت idempotent رکورد؛ تولید رخداد
attendance.checked_in/out.
۴٫۸ — Behavior Analytics Service
یادگیری «امضای رفتاری» هر نیرو و تشخیص ناهنجاری و جایگزینی پنهان.
ویژگیهای استخراجی per shift
- طول مسیر پیمودهشده و توزیع سرعت حرکت
- زمان ماندگاری در هر زون و توالی بازدید زونها
- میزان پوشش/کاملبودن گشت (نسبت زونهای بازدیدشده به الزامی)
- دورههای بیحرکتی/توقف غیرعادی و زمان حضور در پست
- الگوی زمانی رویدادها (ساعتهای فعالیت)
baseline هر نیرو بهصورت پروفایل غلتان (میانگین/انحراف هر ویژگی) نگهداری میشود. تشخیص ناهنجاری چندمتغیره با Isolation Forest (یا Autoencoder در مقیاس دادهٔ بزرگتر) انجام میشود.
۴٫۹ — Alert & Notification Service
دریافت رخدادهای خطر، اعمال قواعد، حذف تکرار (dedup)، تشدید (escalation) و ارسال چندکاناله.
- کانالها: اعلان درونبرنامهای (WebSocket/Push)، پیامک، و وبهوک برای یکپارچگی.
- Dedup با پنجرهٔ زمانی و کلید رخداد برای جلوگیری از سیل هشدار.
- Escalation پلکانی: اگر هشدار در زمان مقرر تأیید/رسیدگی نشد، به سطح بالاتر ارجاع میشود.
- هر هشدار دارای شدت (info/warning/critical) و چرخهٔ حیات (new→ack→resolved) است.
۴٫۱۰ — Realtime, Map & Reporting
Realtime Service موقعیتها و رخدادها را از طریق WebSocket به نقشهٔ داشبورد میرساند. Reporting Service گزارشهای کارکرد، تردد و رویداد را تولید و به Excel/PDF خروجی میدهد.
// پیام WebSocket موقعیت زنده
{ "type": "position", "personId": "...", "floorId": "...",
"x": 12.4, "y": 33.1, "zone": "lobby", "ts": "2026-..." }6اپلیکیشن موبایل (Flutter)
دو نقش در یک اپ: نگهبان (ثبت حضور، وضعیت شیفت/محدوده، اعلانها) و مدیر (پایش و هشدارها). معماری پیشنهادی: لایهای + الگوی BLoC/Riverpod.
- ماژول بیومتریک: دوربین برای چهره (+liveness سمت اپ بهعنوان لایهٔ اول)، و
local_authبرای اثرانگشت. - ماژول BLE: اسکن/ارتباط با تگ امنیتی و گزارش مجاورت.
- ذخیرهٔ امن توکن/کلید با
flutter_secure_storage(Keystore/Keychain). - حالت آفلاین: صف رویدادها و همگامسازی هنگام اتصال (با مهر زمانی سرور هنگام دریافت).
- Push با FCM/APNs برای هشدارها؛ نقشهٔ داخلی طبقه برای نمایش موقعیت.
7داشبورد مدیریتی (Web)
- نقشهٔ تعاملی طبقات با موقعیت زندهٔ نیروها و زونها (Leaflet با لایهٔ تصویر طبقه یا Mapbox GL).
- صفحهٔ رویدادها/هشدارها با فیلتر و چرخهٔ رسیدگی.
- ویرایشگر زون: ترسیم چندضلعی روی نقشهٔ طبقه و تخصیص قواعد دسترسی.
- گزارش کارکرد، بازپخش مسیر (timeline scrubber) و خروجی گزارش.
- مدیریت کاربران/نقشها؛ UI مبتنی بر RBAC (مخفیسازی اقدامات غیرمجاز).
- بهروزرسانی بلادرنگ از طریق WebSocket.
8امنیت و حریم خصوصی
| محور | تصمیم فنی |
|---|---|
| انتقال | TLS 1.3 بیرونی؛ mTLS داخلی بین سرویسها |
| سکون | AES-256-GCM؛ کلید per-tenant از Vault/KMS؛ رمزنگاری ستونی برای داده زیستسنجشی |
| زیستسنجش | نگهداری فقط embedding (نه تصویر خام)؛ امکان template protection/cancelable |
| دسترسی | RBAC + ABAC؛ JWT کوتاهعمر + refresh چرخشی؛ device cert برای دوربین/اسکنر |
| ممیزی | audit_log تغییرناپذیر با زنجیرهٔ هش؛ ثبت هر دسترسی به داده حساس |
| شبکه | جداسازی VLAN دوربینها؛ بدون اینترنت در حالت On-Prem؛ egress کنترلشده |
| اسرار | Vault؛ هیچ رازی در ایمیج/کد/لاگ؛ چرخش دورهای کلیدها |
| ماندگاری | سیاست retention قابلپیکربندی per داده؛ حذف خودکار پس از انقضا |
9مشاهدهپذیری، پایایی و پشتیبانگیری
- Log: ساختیافته (JSON) با correlation/trace id ← Loki.
- Metric: Prometheus (نرخ، تأخیر، خطا per سرویس) + داشبورد Grafana.
- Trace: OpenTelemetry ← Tempo/Jaeger برای ردیابی مسیر رخداد.
- Alert زیرساخت: Alertmanager (سلامت سرویس، صف، GPU، دیسک).
- SLO نمونه: تأخیر تشخیص چهره p95 < ۱s؛ در دسترسبودن سرویس هشدار ۹۹٫۹٪.
- HA/DR: چند replica برای سرویسهای بیحالت؛ replication پایگاهداده؛ پشتیبانگیری زمانبندیشده و تستِ بازگردانی دورهای.
10زیرساخت و استقرار
استقرار با Kubernetes (یا k3s برای On-Prem کوچک). نودهای GPU با nvidia device plugin برای سرویسهای هوش مصنوعی برچسبگذاری میشوند.
# نمونهٔ Deployment سرویس تشخیص چهره روی نود GPU
apiVersion: apps/v1
kind: Deployment
metadata: { name: face-service, namespace: negahban }
spec:
replicas: 2
selector: { matchLabels: { app: face-service } }
template:
metadata: { labels: { app: face-service } }
spec:
nodeSelector: { gpu: "true" }
containers:
- name: face
image: registry.local/negahban/face:1.0
resources:
limits: { nvidia.com/gpu: 1, memory: "8Gi" }
envFrom:
- secretRef: { name: face-secrets }| مقیاس | نمونهٔ توپولوژی |
|---|---|
| لابی/کوچک (≤۱۶ دوربین) | تکنود k3s + ۱ GPU ورودی؛ Postgres+Redis محلی؛ MinIO تکنود |
| سازمانی (≤۶۴ دوربین) | کلاستر ۳ نود + نود GPU میانرده؛ Postgres با replica؛ NATS |
| مرکز حساس (۱۲۸+) | کلاستر چندنود، چند GPU، شبکهٔ ایزوله، افزونگی کامل، Vault اختصاصی |
CI/CD
- Pipeline: lint → unit → build image → scan آسیبپذیری → push → deploy (GitOps/ArgoCD).
- محیطها: dev → staging → prod؛ مهاجرت پایگاهداده نسخهدار (migrations).
- ایمیجهای امضاشده و SBOM برای استقرار در محیط حساس.
11راهبرد تست
| نوع | هدف | ابزار/روش |
|---|---|---|
| واحد (Unit) | منطق سرویسها | go test / pytest / flutter test |
| یکپارچگی | تعامل سرویسها + DB + گذرگاه | محیط docker-compose تست |
| بار (Load) | تأخیر و throughput زیر بار | k6 / Locust؛ شبیهسازی N دوربین و تگ |
| دقت AI | FAR/FRR، دقت liveness | دیتاست برچسبخورده + گزارش ROC |
| امنیت | آسیبپذیری و نفوذ | اسکن SAST/DAST + تست نفوذ |
| پذیرش میدانی | کارکرد واقعی در محل | چکلیست استقرار + سناریوهای واقعی |
12نقشهٔ راه پیادهسازی (بخش به بخش)
ترتیب ساخت بر پایهٔ وابستگیها چیده شده تا در هر فاز یک قابلیتِ قابلنمایش به دست آید. هر فاز خروجی مشخص و معیار پذیرش دارد.
| فاز | ماژولها | خروجی قابلنمایش | وابستگی |
|---|---|---|---|
| ۰ — پیریزی | Repo، CI/CD، Auth، مدل داده، گذرگاه | اسکلت پروژه + لاگین + محیطها | — |
| ۱ — هستهٔ افراد/حضور | Personnel، Attendance، اپ نگهبان (حضور) | ثبت حضور زیستسنجشی واقعی | فاز ۰ |
| ۲ — ویدئو/چهره | Video، Face Service، گالری | تشخیص ورود مجاز/غیرمجاز + هشدار | فاز ۰ |
| ۳ — مکانیابی/زون | RTLS، Zone، Realtime، نقشهٔ داشبورد | موقعیت زنده + کنترل تردد + خروج از محدوده | فاز ۱ |
| ۴ — هوش رفتاری | Behavior، کشف جایگزینی | هشدار ناهنجاری/جایگزینی | فاز ۱،۲،۳ |
| ۵ — گزارش/سختسازی | Reporting، امنیت، Observability، HA | گزارشها + آمادهسازی Production | همه |
13پیوست: نمونهٔ قراردادهای API و رخداد
نمونهٔ Protobuf سرویس چهره (gRPC داخلی)
syntax = "proto3";
package negahban.face.v1;
service FaceService {
rpc Match(stream Frame) returns (stream MatchResult);
rpc Enroll(EnrollRequest) returns (EnrollResponse);
}
message Frame {
string tenant_id = 1;
string camera_id = 2;
bytes image = 3; // JPEG/RAW
int64 ts_unix_ms = 4;
}
message MatchResult {
string person_id = 1; // خالی اگر ناشناس
float score = 2; // شباهت کسینوسی
bool live = 3;
string decision = 4; // authorized | unauthorized
}نمونهٔ رخداد روی گذرگاه
{
"event": "access.unauthorized",
"version": 1,
"tenantId": "0190...",
"personId": null,
"zoneId": "0190-zone-serverroom",
"floorId": "0190-floor-2",
"ts": "2026-06-15T11:20:33Z",
"evidence": { "cameraId": "cam-12", "clipUrl": "s3://events/..." },
"idempotencyKey": "evt-0190..."
}