SkillHubi sisselogimine — arendaja juhend

See dokument kirjeldab, kuidas arenduses SkillHubi igal platvormil sisse logida. Võlulingid (magic link) saadetakse Resendi kaudu kinnitatud skillhub.ee saatedomeenilt igas keskkonnas.

1. Voog ülevaates

mobiilirakendus     skillhub-app.pages.dev          postkast
  │  sisesta e-post       │                             │
  │ ───────────────────── │                             │
  │                       │  POST /api/auth/...         │
  │                       │  → mailer.sendMagicLink     │
  │                       │  ─────────────────────────► │
  │                       │                             │
  │   kasutaja avab lingi süsteemibrauseris             │
  │                       │ GET /api/auth/native-bridge │
  │                       │ → vermib OTT, suunab ümber: │
  │                       │   skillhub://auth/callback  │
  │ ◄────────────────────┘  ?ott=…                      │
  │  appUrlOpen kuulaja → oneTimeToken.verify           │
  │  set-auth-token salvestatud → Pinia user täidetud   │
  │  router.replace('/tabs/home')                       │

Veebiäpp kasutab tavalisi küpsisepõhiseid sessioone ega puuduta OTT silda — ta tarbib võlulingi samas brauseri vahekaardis.

2. Veeb (brauser)

cd apps/web
pnpm dev          # → http://localhost:3000
  1. Klõpsa paremas ülanurgas Logi sisse.
  2. Sisesta e-post lehel /login.
  3. Ava võlulink oma postkastist.
  4. Maandud lehele /welcome koos sessiooniküpsisega.

3. iOS — Xcode'i simulaator või seade

cd apps/mobile
pnpm build && pnpm exec cap sync ios
pnpm exec cap open ios     # avab Xcode

Xcode'is: vali simulaator (iPhone 16 Pro on Galaxy S25 saareekraani paigutusele lähim vaste). Vajuta ▶︎.

  1. Rakendus käivitub aknas /tabs/home ja näitab välja logitud CTA-d.
  2. Toksa Logi sisse → sisesta e-post → toksa Saada sisselogimislink.
  3. Ava võlulink oma postkastist Mobile Safaris.
  4. Safari pöördub /api/auth/native-bridge poole, mis suunab aadressile skillhub://auth/callback?ott=…. iOS küsib, kas avada SkillHub; luba.
  5. Pinia salv tarbib OTT ja suunab sind aknasse /tabs/home.

VITE_API_BASE_URL vaikimisi on https://skillhub-app.pages.dev. Vajadusel sea see failis apps/mobile/.env.local, et osutada kohalikule Wrangleri arendus-API-le.

4. Android — Android Studio (sh. Galaxy S25 emuleerimine)

Vaikimisi AVD-loendis on ainult Pixeli seadmed. Galaxy S25 Ultra profiili saamiseks:

  1. Android Studio → Tools → Device Manager → Create Device.

  2. Vali Phone → Pixel 8 Pro (6,7" 1344×2992 ekraan — lähim S25 Ultra 1440×3120 suhtele) ja nimeta AVD ümber Galaxy S25 Ultra.

  3. Vali süsteemitõmmis API 35 (Android 15), sama põlvkond, millele One UI 7 ehitati. One UI-d AVD-le seaduslikult paigaldada ei saa; kasuta stock Android 15 — see paljastab samad API-d, millega rakendus suhtleb.

  4. Käivita rakendus:

    cd apps/mobile
    pnpm build && pnpm exec cap sync android
    pnpm exec cap open android   # või: pnpm exec cap run android
    
  5. Sisselogimisvoog on identne iOS-iga, ainult et võlulingi ümbersuunamine maandub Chrome'is ja Android pakub SkillHubi avamist skillhub:// skeemi kaudu.

5. E-posti saatmine (Resend)

Võlulingid saadetakse Resendi HTTP API kaudu kinnitatud skillhub.ee saatedomeenilt (vaikimisi info@skillhub.ee). Iga sisselogimiskatse juures pöördub worker mailer.sendMagicLink() poole, mis POSTib aadressile https://api.resend.com/emails; kui RESEND_API_KEY puudub või Resend tagastab mitte-2xx koodi, päring kukub läbi ja kasutaja näeb viga.

Ava url selle seadme süsteemibrauseris, kus rakendus jookseb, et süvalingi üleandmine töötaks. Kui kleebid selle Capacitori WebView'sse endasse, ei käivitu OTT sild. Oluline täpsustus: kui avad lingi oma Maci brauseris (Chrome, Safari), läheb voog katki — macOS-il pole skillhub:// skeemi jaoks ühtki rakendust registreeritud, nii et ümbersuunamine sureb vaikselt ja sa näed tühja lehte.

6. Vajalikud keskkonnamuutujad (Cloudflare Pages)

Võti Kus Otstarve
BETTER_AUTH_SECRET Pages Sessiooni/JWT allkirjastamine
RESEND_API_KEY Pages Võlulingi e-posti saatmine Resendi kaudu
EMAIL_FROM Pages From-päis, vaikimisi SkillHub <info@skillhub.ee>
SEED_TOKEN Pages Kaitseb /api/admin/*
VITE_API_BASE_URL mobile build Suunab WebView'i API päritolu suunas

7. WebView'i silumine

Capacitori WebView on lihtsalt Safari (iOS) või Chrome (Android), seega saad jooksva rakenduse külge ühendada täisväärtusliku DevToolsi sessiooni.

iOS — Safari Web Inspector

  1. Seadmes või simulaatoris: Settings → Safari → Advanced → lülita sisse Web Inspector.
  2. Macis: Safari → Settings → Advanced → lülita sisse Show features for web developers.
  3. Käivita rakendus Xcode'ist (silumiskoosted paljastavad WebView'i; TestFlight ja App Store'i koosted seda ei tee).
  4. Safaris: menüüriba → Develop → [Sinu seade] → SkillHub. Avaneb tavaline DevToolsi aken WebView'i kohal.

Nüüd saad:

  • Vaadata DOM-i — kontrolli, et <ion-input> on tegelikult renderdatud ja selle kõrgus pole null.
  • Lugeda Console'i Vue/Pinia vigade osas, mida iOS-i logi alla neelab (UIScene / RTIInputSystemClient read Xcode'is on müra, mitte vead).
  • Jälgida Network'i osas /api/auth/... päringuid ja kontrollida, et VITE_API_BASE_URL osutab sinna, kuhu eeldad.
  • Käivitada konsoolis document.querySelector('ion-input').shadowRoot, et uurida Ionicu varju-DOM-i, kui sisestus on nähtamatu — see tähendab tavaliselt, et märgistuses on veel vana sildi-ümbristamise muster; vaheta see vastu <IonInput :label="…" fill="outline" /> (Ionic 8 moodne API).

Android — Chrome DevTools

  1. Seadmes: lülita sisse Developer optionsUSB debugging.
  2. Ühenda see Maciga/PC-ga; nõustu RSA sõrmejälje viibaga.
  3. Ava Chrome → chrome://inspect/#devices.
  4. Leia SkillHub Remote Target all ja klõpsa inspect.

DevToolsi liides on identne lauaarvuti Chrome'i sessiooniga ja töötab nii päris seadmete kui ka emulaatori AVD-de vastu.

Mida vaadata, kui "Logi sisse" viib tühjale ekraanile

Sümptom DevToolsis Tõenäoline põhjus
<ion-content> on renderdatud, aga height: 0 Marsruudikomponendis puudub IonPage ümbris
<ion-input> on olemas, aga visuaalselt tühi Vana <label><IonInput/></label> muster iOS-il
Marsruut muutus, aga DOM näitab endist vaadet IonRouterOutlet pole haagitud (vaata App.vue kesta)
Console: Cannot read properties of undefined Pinia salv pole initsialiseeritud; vaata main.ts järjekorda

8. Pakkujate sidumise strateegia (Apple / Google / Smart-ID)

SkillHub pakub nelja sisselogimisviisi: võlulink, Apple, Google ja Smart-ID. Kõik neli viivad ühe users reani inimese kohta, seega on vaja selget sidumisreeglit hetkeks, kui naasev kasutaja logib sisse pakkujaga, mida ta esimesel korral ei kasutanud.

Tõe allikas

  • users — üks rida inimese kohta, võtmestatud id-ga. users.email on unikaalne ja seda käsitletakse kanoonilise tunnusena pakkujate vahel.
  • accounts — üks rida iga (provider, providerAccountId) paari kohta, ühendatud users-iga accounts.user_id kaudu. Selle tabeli haldab Better Auth.
  • users.email_verified_at on usaldusvärav, mis võimaldab automaatset sidumist. Pakkuja e-post läheb arvesse ainult siis, kui see tagastati kinnitatuna (Apple email_verified nõue, Google email_verified nõue, SK ID Solutions tagastab ainult kinnitatud ETSI semantikaga tunnuseid, seega Smart-ID on definitsiooni järgi alati kinnitatud).

Reeglid sisselogimise hetkel

  1. Otsi olemasolevat accounts rida (provider, providerAccountId) järgi.
    • Kui see eksisteerib → logi see users rida sisse. Valmis.
  2. Vastasel juhul tõmba e-post pakkuja nõuetest.
    • Kui pakkuja kinnitab, et e-post on verifitseeritud ja selle e-postiga users rida juba eksisteerib → kirjuta uus accounts rida, mis viitab sellele kasutajale, ja logi sisse. Kasutaja näeb ühekordset toosti: "Sisse logitud Apple'iga — seotud sinu olemasoleva e-posti kontoga."
    • Kui e-post pole kinnitatud või puudub (Apple'i "Peida mu e-post" tagastab releeaadressi, mida me alati usaldame, sest Apple omab seda nimeruumi, kuid teised pakkujad peavad olema kinnitatud) → loo värske users rida + accounts rida.
  3. Smart-ID on eriline: vastus kannab isikukoodi, mitte e-posti. Salvestame selle veergu users.national_identification_number ja käsitleme seda veergu teise unikaalvõtmena sidumiseks.
    • Smart-ID sisselogimine tuntud PNO-ga seob sobiva users reaga sõltumata e-postist.
    • Smart-ID sisselogimine värske PNO-ga loob uue users rea ja palub kasutajal hiljem e-post lisada (kohustuslik enne kui väljamakseid saab teha).

Manuaalne sidumine profiililt

Plaadiplokk "Ühendatud kontod" /tabs/profile lehel laseb kasutajatel:

  • Lisada Apple/Google'i konto e-posti-põhisele sisselogimisele (üheklõpsuline OAuth nõusolek → kirjuta accounts rida).
  • Verifitseerida oma identiteet Smart-ID-ga (juba ühendatud — vt §30.11 failis PROJECT_REFERENCE.md). Õnnestumisel täidetakse users.national_identification_number ja Smart-ID-st saab sellele kasutajale sisselogimisvalik.
  • Eemaldada mis tahes pakkuja seos, kui vähemalt üks tunnustus jääb alles (võlulink kinnitatud e-posti kaudu loeb alati).

Mida me ei tee

  • Me ei loo kunagi automaatselt kontosid kinnitamata pakkuja e-postide jaoks. See avaks konto ülevõtmise augu, kui ründaja kontrollib kirjavea e-posti ja seaduslik kasutaja proovib hiljem õige e-postiga registreeruda.
  • Me ei liida kunagi vaikselt kahte users rida. Kui Smart-ID PNO vastab ühele kasutajale ja Google'i e-post teisele, näidatakse kasutajale lepitusekraani, kus ta saab valida, milline rida jääb alles.

Kus see koodis elab

  • Server: apps/web/server/utils/auth.ts seadistab Better Authi konto sidumise poliitika (accountLinking: { enabled: true, trustedProviders: ['apple', 'google'], allowDifferentEmails: false }). Kui Apple/Google'i tunnustused saabuvad, ühendame pakkujad sealt.
  • Mobiil: apps/mobile/src/views/SignInView.vue paljastab kolm sotsiaalvõrgustiku nuppu. Smart-ID elab praegu /verify/smart-id taga (sisselogimisjärgne identiteedi kinnitamine); tulevane iteratsioon lubab seda ka esmase teguri sisselogimisena, vermides ühekordse žetooni eduka demokeskkonna sessiooni põhjal.

9. Tõrkeotsing

  • "Logi sisse" maandub tühjal ekraanil — tavaliselt tähendab see, et IonHeader kasutas collapse="fade" ilma sidustatud suure tiitli kondenstoolribata. Parandatud failis AppScreen.vue; ehita uuesti + cap sync, kui näed seda vanemal komplektil.
  • E-post ei saabu kunagi — kontrolli, et RESEND_API_KEY on Pages projektis seatud, ja inspekteeri Resendi juhtpaneeli kohaletoimetamise/ bounce-i sündmuste osas. skillhub.ee saatedomeen peab olema Verified olekus.
  • Süvalink ei ava rakendust — kontrolli, et skillhub:// on registreeritud failis apps/mobile/ios/App/App/Info.plist (CFBundleURLSchemes) ja failis apps/mobile/android/app/src/main/AndroidManifest.xml (<data android:scheme="skillhub" />). cap sync taasloob need failist capacitor.config.ts.

10. Pakkujate tunnustuste hankimine

.env.example failid (juur + apps/mobile/) sisaldavad iga pakkuja jaoks kohatäiteid TODO(acquire) markeritega. Täida need pärast alltoodud sammude tegemist.

10.1 Sisselogimine Apple'iga

Vajalikud env-võtmed (juure .env): APPLE_SERVICE_ID (Services ID, nt com.skillhub.web), APPLE_TEAM_ID, APPLE_KEY_ID, APPLE_PRIVATE_KEY (mitmerealine PEM). Mobiilne peegel: VITE_APPLE_SERVICE_ID.

  1. Logi sisse aadressile https://developer.apple.com/account meeskonna konto omanikuna. Meeskond peab olema registreeritud tasulises Apple Developer Programmis ($99/aastas).
  2. Certificates, Identifiers & Profiles → Identifiers:
    • Veendu, et iOS App ID-l (com.skillhub.app) on Sign In with Apple lubatud. Kui ei, redigeeri ja märgista see võimekus.
    • Klõpsa + → Services IDs → Continue. Identifikaator com.skillhub.web, kirjeldus SkillHub Web Auth. Märgista Sign In with Apple, seejärel Configure → primary App ID = iOS App ID, Domains skillhub.app (prod) ja localhost (dev), Return URLs https://skillhub.app/api/auth/callback/apple ja http://localhost:3001/api/auth/callback/apple.
  3. Keys → + (Create a key): nimi SkillHub Sign In With Apple, märgista Sign In with Apple, Configure → primary App ID = iOS App ID. Continue, Register, Download .p8 fail (üks võimalus — hoia turvaliselt). Märgi 10-tähemärgiline Key ID.
  4. Sea env muutujad:
    • APPLE_SERVICE_ID=com.skillhub.web (Services ID, MITTE iOS-i bundle id — Better Auth kasutab seda OAuthi client_id-na).
    • APPLE_TEAM_ID= 10-tähemärgiline ID arendaja portaali ülanurgast.
    • APPLE_KEY_ID= ID 3. sammust.
    • APPLE_PRIVATE_KEY= kleebi kogu .p8 sisu, kaasa arvatud -----BEGIN PRIVATE KEY----- ja -----END PRIVATE KEY----- read. .env failides ümbritse jutumärkidega ja kasuta päris reavahetusi; Cloudflare'is sea saladusena wrangler secret put.
    • VITE_APPLE_SERVICE_ID= peegelda Services ID mobiilse .env-i, et Capgo plugin kasutaks sama OAuthi client_id.
  5. Põlissoiks (iOS rakendus): failis apps/mobile/ios/App/App.xcworkspace, sihtmärk App → Signing & Capabilities → + Capability → Sign In with Apple. Capacitor @capgo/capacitor-social-login loeb komplekti õigusi; põlise poole jaoks JS env muutujat ei vajata.
  6. Test: dev/prod-il on kummalgi oma Services ID tagastus-URL.
    • Veeb: https://skillhub.app/sign-in → toksa Apple → nõusoleku ekraan → ümbersuunamine → /api/auth/callback/apple → küpsis seatud, /tabs/home.
    • iOS: TestFlight koost → toksa Apple → põlislehe → users rida kas luuakse või seotakse-kinnitatud-e-postiga §8 järgi.

10.2 Sisselogimine Google'iga

Vajalikud env-võtmed (juure .env): GOOGLE_OAUTH_CLIENT_ID_WEB, GOOGLE_OAUTH_CLIENT_SECRET, GOOGLE_OAUTH_CLIENT_ID_IOS, GOOGLE_OAUTH_CLIENT_ID_ANDROID. Mobiilne peegel: VITE_GOOGLE_OAUTH_CLIENT_ID_WEB, VITE_GOOGLE_OAUTH_CLIENT_ID_IOS.

  1. Logi sisse aadressile https://console.cloud.google.com/. Loo projekt skillhub-prod (ja skillhub-dev lokaalseks) või vali olemasolev.
  2. APIs & Services → OAuth consent screen:
    • Kasutaja tüüp External, rakenduse nimi SkillHub, toe e-post, logo, domeen skillhub.app, arendaja kontakt.
    • Skoobid: openid, email, profile. Tundlikke skoope ei kasuta — hoiab meid Google'i kinnitamise järjekorrast eemal.
    • Testi kasutajad: lisa arendusmeeskonna e-postid, kuni rakendus on Published (nupp consent screen lehe ülaosas).
  3. APIs & Services → Credentials → + Create Credentials → OAuth client ID:
    • Rakenduse tüüp Web application, nimi SkillHub Web.
    • Lubatud JavaScripti päritolud: https://skillhub.app, http://localhost:3001.
    • Lubatud ümbersuunamise URI-d: https://skillhub.app/api/auth/callback/google, http://localhost:3001/api/auth/callback/google.
    • Salvesta → kopeeri kliendi ID + saladus väljadesse GOOGLE_OAUTH_CLIENT_ID_WEB / GOOGLE_OAUTH_CLIENT_SECRET.
  4. Korda Create Credentials → OAuth client ID tüübiga iOS, bundle ID com.skillhub.app. Kopeeri saadud kliendi ID väljale GOOGLE_OAUTH_CLIENT_ID_IOS (põlistele klientidele saladust pole). Korda Androidi jaoks (vajalik SHA-1 sõrmejälg) → GOOGLE_OAUTH_CLIENT_ID_ANDROID.
  5. Test:
    • Veeb: https://skillhub.app/sign-in → Google → nõusolek → /api/auth/callback/google.
    • iOS: toksa Google failis SignInView.vue → ASWebAuthenticationSession avaneb → nõusolek → süvalink tagasi skillhub://oauth/google.

10.3 Smart-ID (tootmine)

Vajalikud env-võtmed (juure .env): SMART_ID_RP_UUID, SMART_ID_RP_NAME, SMART_ID_BASE_URL=https://rp-api.smart-id.com/v3, pluss mTLS kliendisertifikaat + võti Wrangleri saladustena (mitte versioonihalduses).

  1. Saada e-kiri aadressile support@sk.ee registreeritud SkillHub Estonia domeenilt, milles teatad kavatsust liituda Smart-ID Relying Party võrgustikuga. Lisa ettevõtte registreerimisnumber ja tootmise hostinimi, millelt päringud lähtuvad.
  2. Allkirjasta SK Master Service Agreement + Smart-ID Authentication Service lisand (~1 nädal juriidilist edasi-tagasi). Andmekaitse spetsialist peab allkirjastama isikukoodide töötlemist katva DPA.
  3. SK väljastab:
    • Tootmise RP UUID (32 tähemärki) → SMART_ID_RP_UUID.
    • Tootmise RP nime (kuvasõne, mida näidatakse Smart-ID rakenduses) → SMART_ID_RP_NAME (peab olema täpselt nende heaks kiidetud juriidiline nimi).
    • Tootmise mTLS kliendisertifikaat + privaatvõti. SK nõuab tootmise liikluseks mTLS-i; demoliivakast seda ei nõua.
  4. Salvesta sertifikaat + võti Cloudflare Workeri saladustena: wrangler secret put SMARTID_CLIENT_CERT_PEM, wrangler secret put SMARTID_CLIENT_KEY_PEM. Uuenda apps/web/server/utils/smartId.ts, et lisada need fetch kõnele, kui RP_UUID lülitub demo-väärtuselt eemale.
  5. Test: SK pakub "go-live" kontrollnimekirja pluss väikese testitehingute eraldise. Käivita samad voolud, mis täna demo liivakastis edukalt läbivad (30303039914 õnnestub, 30303039816 keeldub), kuid päris PNO koodide vastu.

10.4 Capgo sotsiaalvõrgustiku sisselogimise plugin

Kui Apple ja Google'i tunnustused on paigas, paigalda plugin (pnpm --filter @skillhub/mobile add @capgo/capacitor-social-login), seadista see failis apps/mobile/src/main.ts iOS-i kliendi ID-dega, seejärel asenda socialNotice pügalad failis apps/mobile/src/views/SignInView.vue SocialLogin.login() kõnedega. Veebipool jääb Better Auth → /api/auth/sign-in/social, sest Capgo plugin tarnib ainult põliseid SDK-sid.

11. Push-teavitused — FCM (Android) ja APNS (iOS)

Töövõtu päringu teavitused kirjutavad juba ridu tabelisse notifications, nii et rakendusesisene postkast töötab ilma välisteenusteta. Push'i levitus (apps/web/server/utils/notify.ts → dispatchPush) on nüüd ühendatud FCM HTTP v1 API-ga: kui FCM_SERVICE_ACCOUNT_JSON on Cloudflare Pages'i saladusena seatud, saadab iga Androidi (ja FCM-iga ühendatud iOS) tunnus päris push-teate. Saladuse puudumisel langeb kood vaikselt tagasi console.info stub'ile, nii et lokaalne dev jätkab toimimist. Mobiilne liim, tabel device_tokens (migratsioon 0013_many_silhouette) ja registreerimise otsapunkt on kõik valmis.

11.1 Mobiilne liim (juba ühendatud)

  • @capacitor/push-notifications@^8 on paigaldatud asukohas apps/mobile.
  • apps/mobile/src/composables/usePushNotifications.ts küsib loa, registreerub, kuulab registration sündmust ja POST-ib { token, platform } aadressile /api/me/device-tokens. Tunnuse rotatsioon POST-itakse uuesti automaatselt (server upsert-ib unikaalse token veeru järgi ja tühjendab revokedAt).
  • apps/mobile/src/App.vue kutsub initPushNotifications(), kui Pinia auth-store teatab sisse logitud kasutajast, ja teardownPushNotifications() välja logimisel (mis DELETE-ib tunnuse, et märgistada see serveripoolselt eemaldatuks).
  • Vastav serveri marsruut elab failis apps/web/server/api/me/device-tokens.post.ts (ja .delete.ts); skeem on failis packages/db/src/schema/communications.ts → deviceTokens.

Uuele pluginale olemasolevatest checkout-idest peale jõudmiseks:

pnpm --filter @skillhub/mobile install
cd apps/mobile && npx cap sync

11.2 Firebase Cloud Messaging (Android)

  1. Loo Firebase'i projekt aadressil https://console.firebase.google.com.
  2. Lisa Androidi rakendus — paketinimi ee.skillhub.app (vastab failis apps/mobile/android/app/build.gradle olevale applicationId-le). Laadi alla google-services.json ja paiguta see asukohta apps/mobile/android/app/. Kommiti see (saladusi pole — fail on Google'i API-võtme dokumentatsiooni järgi avalikult mõeldud) või suuna CI kaudu, kui meeskond eelistab. Rakenduse tasemel build.gradle sisaldab juba kaitstud apply plugin: 'com.google.gms.google-services' plokki, mis aktiveerub hetkel, kui JSON on kohal — täiendavaid Gradle muudatusi pole vaja.
  3. Gradle'i ühendus on juba paigas versioonil 4.4.4 (Capacitori skafold kasutab vana buildscript-süntaksi — ekvivalentne Firebase'i uuemale Plugin DSL-ile):
    • apps/mobile/android/build.gradle: classpath 'com.google.gms:google-services:4.4.4'
    • apps/mobile/android/app/build.gradle: tingimuslik apply plugin: 'com.google.gms.google-services' Käsitsi muudatusi vaja pole — mõlemad failid on kommititud.
  4. Firebase → Project Settings → Service accounts → "Generate new private key", lae JSON alla ja salvesta Cloudflare'i: wrangler secret put FCM_SERVICE_ACCOUNT_JSON < firebase-adminsdk.json.
  5. Serveri pool: dispatchPush (apps/web/server/utils/notify.ts) allkirjastab teenusekonto põhjal RS256 JWT-i crypto.subtle abil, vahetab selle OAuth2 ligipääsutoken'i vastu ja POST-ib https://fcm.googleapis.com/v1/projects/<project-id>/messages:send iga Androidi (ja FCM-iga ühendatud iOS) tunnuse kohta. Aegunud tunnused (HTTP 404 / UNREGISTERED) revokeeritakse automaatselt tabelis device_tokens, et lõpetada uuesti proovimine.

11.3 Apple Push Notification service (iOS)

  1. Apple Developer portaalis luba Push Notifications võimekus App ID-l ee.skillhub.app. Ava apps/mobile/ios/App/App.xcworkspace, vali App-i sihtmärk → Signing & Capabilities → "+ Capability" → Push Notifications.
  2. Loo APNs autentimisvõti (Keys → "+", märgista "Apple Push Notifications service", lae alla .p8). Märgi Key ID ja Team ID — mõlemat on vaja.
  3. Salvesta tunnustused Cloudflare'i saladustena:
    wrangler secret put APNS_AUTH_KEY_P8 < AuthKey_XXXX.p8
    wrangler secret put APNS_KEY_ID            # 10-tähemärgiline sõne
    wrangler secret put APNS_TEAM_ID           # 10-tähemärgiline sõne
    wrangler secret put APNS_BUNDLE_ID         # ee.skillhub.app
    
    Lisa APNS_USE_SANDBOX=1 TestFlighti/Xcode'i koostudele; eemalda (või 0) tootmise jaoks.
  4. Serveri pool: failis dispatchPush allkirjasta JWT (ES256, päised { alg: "ES256", kid: APNS_KEY_ID }, kasulik koormus { iss: APNS_TEAM_ID, iat }) ja POST-i aadressile https://api.sandbox.push.apple.com/3/device/<token> (liivakast) või https://api.push.apple.com/3/device/<token> (tootmine), pead apns-topic: ee.skillhub.app ja teate tekstiga.

11.4 Veebi push (Nuxt PWA, valikuline)

Kui soovid lauatööandjatele brauseri push'i, paigalda workeri sisse web-push, genereeri VAPID võtmepaar (npx web-push generate-vapid-keys) ja salvesta võtmed Cloudflare'i saladustena VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY. Telli brauseris navigator.serviceWorker.register(...).pushManager.subscribe kaudu ja POST-i PushSubscription JSON aadressile /api/me/device-tokens parameetriga platform: 'web'. dispatchPush kutsub seejärel iga web rea kohta webpush.sendNotification-it.

11.5 Otsast otsani kontrollimine

  1. Logi sisse päris seadmel (iOS Simulator EI saa APNS-i).
  2. Käivita töövõtu päringu POST oma konto vastu teisest sessioonist.
  3. Kontrolli wrangler tail apps/web — kui FCM_SERVICE_ACCOUNT_JSON on seatud, ei tohiks ühtegi (stub) rida ilmuda; tõrked tulevad välja kujul [notify] FCM send failed koos v1 vea kerega.
  4. Märk / salve sissekanne peaks ilmuma sekundi-paari jooksul.

Kuni §11 on töös, on rakendusesisene /api/me/notifications voog ainus tõe allikas töövõtu päringu hoiatuste jaoks ja töölise avalehe küsib neid igal laadimisel.