Merge release/delivery (IAM single sign-on) into the triage work

Brings the four release/delivery commits (IAM SSO for the admin panel,
both apps and the API; IAM env in docker-compose) onto fix/issues-triage.

Conflicts:
- customer-auth.service.ts imports: both kept.
- both apps' api/client.ts: both kept (AccountingBalance/WageQuote, and
  iamAppUrl).
- all build output (admin-panel, user-app, user-app-v2 dist, and the api
  release bundle): rebuilt from the merged source instead of picking a
  side.

Fixed while verifying:
- The IAM change calls iam.browserBootstrapUrl after every login, but
  the identity-service stand-ins in three test files lacked it. 15 tests
  failed on release/delivery itself.
- SMS relay: SMS_RELAY_PLATFORM was read but never sent, so the gateway
  never got `platform` (documented body: phone, host, text, platform).
  relayConfig() now returns it ("default" → null) and the request carries
  it. sms.service.spec now passes.

All 249 API tests pass; the three front-ends type-check and build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
s.esmaeili
2026-10-10 09:03:53 +03:30
co-authored by Claude Opus 5.5
315 changed files with 82919 additions and 7020 deletions
+32 -4
View File
@@ -12,7 +12,7 @@
| موضوع | تصمیم |
| --- | --- |
| رابط کاربری | **هیچ تغییری نمی‌کند**؛ نه دکمه SSO، نه ریدایرکت، نه صفحه جدید |
| رابط کاربری | فرم ورود همان است. با IAM روشن، یک پرش بی‌صدای `prompt=none` و صفحه `/auth/iam/callback` اضافه شده تا ورود مشترک با همکار کار کند |
| جای اتصال | فقط همان یک نقطه‌ای که رمز بررسی می‌شد (`AuthService.login`) |
| پیش‌فرض | خاموش (`IAM_ENABLED=false`) — رفتار سامانه دقیقاً مثل امروز |
| در دسترس نبودن IAM | بازگشت خودکار به بررسی رمز محلی ⇒ ورود ادمین‌ها قطع نمی‌شود |
@@ -86,8 +86,9 @@ curl -X POST https://auth.example.com/api/v1/admin/clients \
}'
```
> `redirect_uris` در این حالت استفاده نمی‌شود (جریان مرورگری نداریم) ولی
> IAM آن را اجباری می‌داند؛ یک آدرس معتبر بگذارید.
> `redirect_uris` آدرس callback فرانت است و باید دقیقاً با صفحه‌ای که مرورگر
> باز می‌کند یکی باشد. برای اپ کاربر و پنل ادمین، و برای دولوپ و پروداکشن،
> هر کدام یک خط جدا. جزئیات در بخش «ورود مشترک با همکار».
### گام ۲ — تنظیم `.env`
@@ -192,7 +193,34 @@ POST /api/iam/backchannel-logout ← این آدرس را در IAM به‌عن
---
## ۶. تست
## ۶. ورود مشترک با همکار
کوکی نشست روی خود IAM است (`iam.montest.ir`) و بین دامنه‌ها مشترک نمی‌شود.
ورود در یک سامانه فقط وقتی سامانهٔ دیگر را هم باز می‌کند که:
1. ورود محلی بلیت مرورگر گرفته باشد و فرانت به `iamBootstrapUrl` رفته باشد.
2. سامانهٔ دوم بدون توکن محلی، `prompt=none` بزند و callback **همان صفحه** باشد.
3. همان شماره موبایل در سامانهٔ دوم از قبل حساب داشته باشد. IAM حساب gold-bank
یا همکار را نمی‌سازد.
کلاینت gold-bank جدا از `hamkar_server` است (`goldbank_api`). آدرس‌ها عیناً،
هر کدام یک خط در فرم IAM و با کاما در env:
| نقش | callback (آدرس‌های بازگشت) | بعد از خروج |
| --- | --- | --- |
| اپ کاربر | `IAM_REDIRECT_URI` و `IAM_REDIRECT_URIS` | `IAM_POST_LOGOUT_REDIRECT_URI` و `IAM_ALLOWED_RETURN_URLS` |
| پنل ادمین | `IAM_ADMIN_REDIRECT_URI` و `IAM_ADMIN_REDIRECT_URIS` | `IAM_ADMIN_POST_LOGOUT_REDIRECT_URI` و `IAM_ADMIN_ALLOWED_RETURN_URLS` |
فرانت آدرس خودش را می‌فرستد (`origin` + `/auth/iam/callback`؛ پنل شعبه پیشوند
`/branch` دارد). اگر آن رشته در فهرست نباشد، بررسی بی‌صدا انجام نمی‌شود و
صفحهٔ لاگین محلی می‌ماند. خروج هم اگر مقصدش ثبت نشده باشد به IAM نمی‌رود.
وقتی `IAM_ENABLED` خاموش است، `sso/start` مقدار `enabled: false` می‌دهد و
`sso/logout-url` مقدار `logout_url: null`. هیچ پیام خطایی برای خروج لازم نیست.
---
## ۷. تست
```bash
cd apps/api