ภาษาไทย English ← หน้าแรก / Home

นโยบายความเป็นส่วนตัว — Siriraj Rx Shift (Google Calendar Sync)

อัปเดตล่าสุด: 3 สิงหาคม 2569 (2026-08-03) · English version below

เอกสารนี้ครอบคลุมเฉพาะฟีเจอร์ Google Calendar Sync ของระบบ Siriraj Rx Shift ("ระบบ", "เรา") ซึ่งเป็นระบบจัดตารางเวรภายในของฝ่ายเภสัชกรรม โรงพยาบาลศิริราช (ระบบหลักใช้ชื่อ + รหัสผ่านภายใน ไม่ผ่านบัญชี Google และไม่ได้เข้าถึงข้อมูล Google ของผู้ใช้)

1. ภาพรวม

ฟีเจอร์ Google Calendar Sync เป็นทางเลือกเสริมแบบ opt-in ที่ช่วยให้ผู้ใช้เห็นเวรของตัวเอง ในปฏิทิน Google ส่วนตัวโดยอัตโนมัติ โดยไม่ต้องคัดลอกด้วยมือ

ผู้ใช้ที่ไม่กดเปิดฟีเจอร์นี้ จะไม่ถูกขอสิทธิ์ Google ใดๆ ทั้งสิ้น และใช้ระบบได้ตามปกติครบทุกฟังก์ชัน

2. สิทธิ์ (OAuth scope) ที่เราขอ และใช้ทำอะไร

ฟีเจอร์นี้ทำงานบน Google Apps Script โปรเจกต์แยกต่างหาก (calendar-sync-app) ซึ่งขอสิทธิ์ เพียง 4 รายการนี้เท่านั้น — ตรงกับที่ประกาศไว้ใน manifest ของแอปทุกตัว ไม่มีมากกว่านี้

Scopeใช้ทำอะไรขอบเขตที่จำกัดไว้
.../auth/calendar สร้าง / แก้ไข / ลบ event ที่แทนเวรของผู้ใช้เอง และให้ผู้ใช้เลือกหรือสร้างปฏิทินปลายทางได้ (เช่น สร้างปฏิทินแยกชื่อ "Siriraj Rx Shifts" เพื่อไม่ให้ปนกับปฏิทินส่วนตัว) แก้ไข/ลบเฉพาะ event ที่ระบบนี้สร้างเอง — อ้างอิงจากตาราง "เวร ↔ event ID" ที่เก็บในพื้นที่ส่วนตัวของผู้ใช้ · ไม่นำเนื้อหา event ใดของผู้ใช้ไปเก็บหรือส่งออก · ไม่เข้าถึงปฏิทินของผู้อื่น
.../auth/script.scriptapp สร้าง / ลบ time-based trigger ในบัญชีของผู้ใช้เอง เพื่อให้ปฏิทินอัปเดตตามเวรล่าสุด แม้ผู้ใช้ปิดแอปอยู่ ติดตั้ง trigger ได้ตัวเดียว (_autoSyncTick) · ผู้ใช้เปิด/ปิดเองได้ตลอด · ไม่ให้สิทธิ์เข้าถึงบริการ Google อื่นเพิ่ม
.../auth/script.external_request เรียก HTTPS ออกไปยังฐานข้อมูลของเราเอง (Firebase Realtime Database) เพื่ออ่าน "เวรล่าสุดของผู้ใช้คนนี้" และเขียนใบเสร็จยืนยันว่าซิงค์สำเร็จ ปลายทางเดียวคือ siriraj-rx-shift-default-rtdb.asia-southeast1.firebasedatabase.app · ไม่มีบริการบุคคลที่สามเกี่ยวข้อง · ไม่ส่งข้อมูล Google ของผู้ใช้ออกไป
.../auth/userinfo.email อ่านอีเมลของบัญชี Google ที่ผู้ใช้เลือก เพื่อแสดงให้เห็นว่ากำลังจะซิงค์เข้าบัญชีไหน และกันการซิงค์ผิดบัญชี ใช้แสดงผลและจับคู่บัญชีเท่านั้น · ไม่ส่งอีเมลออกนอกระบบ · ไม่ใช้ทำการตลาด

ทำไมต้องใช้ calendar ไม่ใช่ calendar.events ที่แคบกว่า: เพราะฟีเจอร์นี้ให้ผู้ใช้ เลือกปฏิทินปลายทางหรือสร้างปฏิทินใหม่แยกต่างหาก ได้ ซึ่งเป็นการจัดการตัวปฏิทิน ไม่ใช่แค่ event — calendar.events ทำไม่ได้ ทางเลือกเดียวถ้าใช้ scope แคบกว่านี้คือบังคับเขียนลงปฏิทินหลักของผู้ใช้เสมอ ซึ่งเป็นผลเสียต่อความเป็นส่วนตัวของผู้ใช้เองมากกว่า (ปนกับปฏิทินส่วนตัว ปิด/ซ่อนแยกไม่ได้)

3. ข้อมูลที่เราเข้าถึง เก็บ และเก็บไว้ที่ไหน

ข้อมูลเก็บที่ไหนใครเข้าถึงได้
OAuth access / refresh token เราไม่เก็บเลย — Google Apps Script เป็นผู้ถือและจัดการทั้งหมดในโครงสร้างพื้นฐานของ Google เราไม่มีสำเนา ไม่มีที่เก็บ ไม่มีทางส่งต่อ ไม่มีใครในฝั่งเรา
Mapping "เวร ↔ event ID" และปฏิทินปลายทางที่เลือก PropertiesService.getUserProperties() — พื้นที่เก็บข้อมูลส่วนตัวของผู้ใช้แต่ละคน ที่ Google จัดสรรให้ ผูกกับบัญชีผู้ใช้คนนั้นโดยตรง เฉพาะการรันสคริปต์ในนามของผู้ใช้คนนั้นเอง — ผู้พัฒนาเปิดดูไม่ได้ ผู้ใช้คนอื่นเข้าไม่ถึง แม้แต่ผู้ดูแลระบบก็อ่านไม่ได้
อีเมลบัญชี Google ที่เลือก หน่วยความจำชั่วคราวระหว่างรัน + PropertiesService ของผู้ใช้เอง เช่นเดียวกับข้างบน
รายการเวรของผู้ใช้ (feed) Firebase Realtime Database region asia-southeast1 — เขียนโดยระบบหลัก อ่านโดย trigger ของผู้ใช้ ดูข้อ 5.6
ใบเสร็จยืนยันการซิงค์ (ack) Firebase เช่นกัน — เก็บแค่จำนวน event ที่สร้าง/แก้/ลบ และเวลา ไม่มีเนื้อหา event ดูข้อ 5.6

สิ่งที่ปรากฏใน calendar event: วันที่ · เวลาเริ่ม-จบ · ประเภทเวร (เช่น "เวรเช้า") · หน่วยงาน/ห้องที่ประจำ เท่านั้น

สิ่งที่ไม่มีวันเกี่ยวข้อง: ข้อมูลผู้ป่วย · ข้อมูลสุขภาพ (PHI/PHR) · เลข HN · ข้อมูลเวชระเบียน — ระบบทั้งระบบเป็นระบบจัดเวรบุคลากร ไม่ใช่ระบบเวชระเบียน จึงไม่เคยแตะข้อมูลเหล่านี้เลยตั้งแต่ต้น

ทิศทางการไหลของข้อมูลเป็นทางเดียว: ระบบ → ปฏิทินของผู้ใช้ — เราไม่แตะต้อง event ที่ระบบไม่ได้สร้าง ไม่เข้าถึงปฏิทินอื่นที่ผู้ใช้ไม่ได้เลือก และไม่ดึงเนื้อหาใดจากปฏิทินกลับเข้าระบบ — ระหว่างซิงค์ ระบบดูรายการ event เฉพาะในช่วงวันที่ของชุดเวรบนปฏิทินปลายทาง เพียงเพื่อยืนยันว่า event ที่ระบบสร้างไว้ยังอยู่ครบ (ตรวจเฉพาะ event ID กับช่อง location) ไม่อ่านเนื้อหา และไม่มีข้อมูลของ event อื่นถูกเก็บหรือส่งออก

4. วัตถุประสงค์การใช้ข้อมูล และ Limited Use

ใช้เพื่อวัตถุประสงค์เดียวคือ เตือนความจำเวรทำงาน ของผู้ใช้ผ่านปฏิทินที่ผู้ใช้ใช้อยู่แล้ว

การใช้งานและถ่ายโอนข้อมูลที่ได้รับจาก Google API เป็นไปตาม Google API Services User Data Policy รวมถึงข้อกำหนด Limited Use โดยเฉพาะ เราขอยืนยันว่า:

5. มาตรการคุ้มครองข้อมูล (Data Protection)

5.1 การเข้ารหัสระหว่างรับส่ง (in transit)

การรับส่งข้อมูลทุกเส้นทางบังคับใช้ HTTPS/TLS 1.2 ขึ้นไป ไม่มีช่องทางที่เป็น HTTP ธรรมดา: เบราว์เซอร์ผู้ใช้ ↔ Apps Script web app · Apps Script ↔ Google Calendar API · Apps Script ↔ Firebase Realtime Database (UrlFetchApp ปฏิเสธ certificate ที่ไม่ถูกต้องโดยอัตโนมัติ)

5.2 การเข้ารหัสขณะจัดเก็บ (at rest)

ข้อมูลทั้งหมดอยู่ในโครงสร้างพื้นฐานของ Google (Apps Script PropertiesService, Google Sheets, Firebase Realtime Database) ซึ่ง เข้ารหัสขณะจัดเก็บด้วย AES-256 โดยค่าเริ่มต้น เราไม่มีเซิร์ฟเวอร์ ไม่มีฐานข้อมูล และไม่มีดิสก์ของตัวเองที่เก็บข้อมูลผู้ใช้เลยแม้แต่จุดเดียว

5.3 การจำกัดสิทธิ์เข้าถึง — ผู้พัฒนาเข้าถึงข้อมูล Google ของผู้ใช้ไม่ได้เลย

นี่คือมาตรการที่แข็งแรงที่สุดของสถาปัตยกรรมนี้ และเป็นผลจากการออกแบบโดยตั้งใจ:

5.4 การจัดการ token

เราไม่เก็บ ไม่บันทึก (log) และไม่ส่งต่อ OAuth token ใดๆ ทั้ง access token และ refresh token อยู่ในความดูแลของ Google Apps Script ทั้งหมด เมื่อผู้ใช้ถอนสิทธิ์ที่ Google Account permissions สิทธิ์จะหมดผลทันทีโดยไม่ต้องรอให้ฝั่งเราทำอะไร

5.5 การแยกโปรเจกต์เพื่อจำกัดความเสียหาย (least privilege by isolation)

ฟีเจอร์ Calendar ถูกแยกออกเป็น Apps Script โปรเจกต์และ Google Cloud project ต่างหาก จากระบบหลักโดยเจตนา ระบบหลัก (ที่มีสิทธิ์ระดับสูงกว่าสำหรับงานหลังบ้านของผู้ดูแล) และโปรเจกต์ Calendar ไม่แชร์ credential กันเลย ผู้ใช้ที่กดเชื่อมต่อปฏิทินจึงถูกขอสิทธิ์เฉพาะ 4 รายการในข้อ 2 เท่านั้น ไม่มีสิทธิ์ของระบบหลังบ้านปนเข้ามาแม้แต่ตัวเดียว

5.6 ข้อมูลตารางเวรใน Firebase (feed / ack)

calFeed เก็บรายการเวรของผู้ใช้ ระบุด้วยชื่อเรียกภายในหน่วยงาน (ไม่ใช่อีเมล ไม่ใช่ Google ID) เนื้อหาคือข้อมูลชุดเดียวกับตารางเวรกลางที่บุคลากรในหน่วยงานทุกคน เห็นอยู่แล้วเป็นปกติ ส่วน calAck เก็บเพียงตัวเลขสรุป (สร้าง/แก้/ลบ กี่รายการ เมื่อไหร่) ไม่มีเนื้อหา event

ฐานข้อมูลนี้อยู่ใน region asia-southeast1 (สิงคโปร์) เข้ารหัสขณะจัดเก็บ และ ไม่มีข้อมูลที่ได้จาก Google API ของผู้ใช้เก็บอยู่เลย — ไม่มี token ไม่มี event ID ไม่มีเนื้อหาปฏิทิน

5.7 การบันทึกและตรวจสอบย้อนหลัง

การรันสคริปต์ทุกครั้งถูกบันทึกโดยอัตโนมัติใน Google Cloud Logging (Stackdriver) ตามค่าที่ตั้งไว้ในโปรเจกต์ และการซิงค์แต่ละรอบเขียน "ใบเสร็จ" (calAck) ที่ระบุเวลาและจำนวน event ที่สร้าง/แก้/ลบ เพื่อให้ตรวจย้อนได้ว่าปฏิทินถูกแก้ไปกี่รายการเมื่อไหร่ บันทึกเหล่านี้ ไม่บันทึกเนื้อหา event และไม่บันทึก token ใดๆ

5.8 ระยะเวลาเก็บรักษาและการลบ

ข้อมูลเก็บนานเท่าไร
Mapping เวร ↔ event IDตราบเท่าที่ผู้ใช้ยังเปิดฟีเจอร์นี้ · ลบทันทีเมื่อผู้ใช้กด "ยกเลิกการเชื่อมต่อ"
อีเมลบัญชีที่ผูกไว้เช่นเดียวกัน
calFeed ของผู้ใช้เก็บเวรรุ่นล่าสุดของแต่ละเดือนที่เผยแพร่ · เมื่อเวรเดือนใดเปลี่ยน ข้อมูลเดือนนั้นถูกเขียนทับทั้งก้อน ไม่เก็บประวัติการแก้ไข
calAck (ใบเสร็จ)เก็บเฉพาะรายการล่าสุด · ถูกเขียนทับทุกครั้งที่ซิงค์

เมื่อผู้ใช้กด "ยกเลิกการเชื่อมต่อ" ระบบจะ (1) ลบ event ที่ระบบสร้างไว้ทั้งหมด ออกจากปฏิทินผู้ใช้ (2) ลบ mapping และการตั้งค่าออกจาก PropertiesService (3) ลบ trigger ที่ติดตั้งไว้ และ (4) เพิกถอน authorization ของสคริปต์ — ทั้งหมดนี้จบภายในการกดปุ่มครั้งเดียว (หาก event ใดลบไม่สำเร็จในจังหวะนั้น เช่น เข้าถึงปฏิทินไม่ได้ชั่วคราว ระบบจะแจ้งผู้ใช้ และเก็บ mapping เฉพาะรายการนั้นไว้เพื่อตามลบให้สำเร็จในครั้งถัดไป ไม่ปล่อยเป็น event ค้าง)

5.9 การรับมือเหตุละเมิดข้อมูล

หากพบเหตุที่กระทบต่อข้อมูลผู้ใช้ เราจะ (1) ระงับฟีเจอร์และเพิกถอน authorization ทันที (2) แจ้งผู้ใช้ที่ได้รับผลกระทบทางอีเมลและผ่านประกาศในระบบ ภายใน 72 ชั่วโมง นับจากเวลาที่ทราบเหตุ และ (3) แจ้ง Google ผ่านช่องทางที่กำหนด หากเหตุนั้นเกี่ยวข้องกับข้อมูลจาก Google API

5.10 บุคลากรที่เข้าถึงได้

ระบบนี้พัฒนาและดูแลโดย ผู้พัฒนาเพียงคนเดียว (ผู้ติดต่อในข้อ 9) ไม่มีพนักงาน ไม่มีผู้รับจ้างช่วง ไม่มีบุคคลที่สามที่ได้รับสิทธิ์เข้าถึง บัญชี Google ของผู้พัฒนาที่เป็นเจ้าของโปรเจกต์ เปิดใช้ การยืนยันตัวตนสองชั้น (2-Step Verification) อยู่

6. การแชร์ข้อมูลกับบุคคลที่สาม

เราไม่แชร์ข้อมูลใดๆ ที่ได้จาก Google API กับบุคคลที่สามรายใดทั้งสิ้น ไม่มีบริการวิเคราะห์ (analytics) ไม่มี tracker ไม่มีโฆษณา ไม่มี CDN ภายนอกที่รับข้อมูลผู้ใช้ ผู้ประมวลผลข้อมูลรายเดียวคือ Google LLC ในฐานะผู้ให้บริการโครงสร้างพื้นฐาน (Apps Script, Calendar, Firebase)

7. สิทธิ์ของผู้ใช้

ผู้ใช้มีสิทธิ์เข้าถึง แก้ไข ขอสำเนา คัดค้านการประมวลผล และขอลบข้อมูลของตน ตาม พ.ร.บ. คุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562 (PDPA) โดยดำเนินการได้เองทันทีดังนี้:

  1. ยกเลิกการเชื่อมต่อในแอป — กดปุ่ม "ยกเลิกการเชื่อมต่อ" ในหน้า "ตั้งค่าปฏิทินเวร" ระบบจะลบ event ทั้งหมดที่สร้างไว้ + ลบข้อมูลที่เก็บไว้ + ลบ trigger ให้อัตโนมัติ
  2. ลบเฉพาะ event โดยไม่ตัดการเชื่อมต่อ — กดปุ่ม "ล้าง event เวรทั้งหมด"
  3. ถอนสิทธิ์จากฝั่ง Google โดยตรง — ที่ Google Account permissions เลือกแอป "Siriraj Rx Shift Calendar" แล้วกดยกเลิก
  4. ปิดการอัปเดตอัตโนมัติอย่างเดียว — สลับสวิตช์ "อัปเดตอัตโนมัติ" (trigger จะถูกลบ · event ที่ซิงค์ไว้ยังอยู่)

คำขอลบข้อมูลหรือคำถามอื่นๆ ส่งได้ที่อีเมลในข้อ 9 เราจะดำเนินการภายใน 30 วัน

8. เด็กและเยาวชน

ระบบนี้ใช้งานโดยบุคลากรวิชาชีพเภสัชกรรมเท่านั้น ไม่ได้ออกแบบหรือมุ่งหมายให้ผู้มีอายุต่ำกว่า 18 ปีใช้งาน และเราไม่เก็บข้อมูลจากผู้เยาว์โดยเจตนา

9. การเปลี่ยนแปลงนโยบายนี้ และการติดต่อ

หากมีการเปลี่ยนแปลงสาระสำคัญ เราจะปรับวันที่ "อัปเดตล่าสุด" ด้านบน และแจ้งผู้ใช้ผ่านประกาศในระบบ

ผู้ควบคุมข้อมูล / ผู้ติดต่อ: Norapol Uttho — norapol.uttho@gmail.com
เว็บไซต์แอป: https://sirxshift.com/

Privacy Policy — Siriraj Rx Shift (Google Calendar Sync)

Last updated: 3 August 2026 · ดูฉบับภาษาไทยด้านบน

This is a complete English translation of the Thai text above, provided for reviewer convenience. In case of discrepancy, the Thai text is authoritative.

1. Overview

Siriraj Rx Shift ("the app", "we") is an internal duty-roster system for the Pharmacy Department, Siriraj Hospital, Bangkok, Thailand. The Google Calendar Sync feature is an optional, opt-in add-on that mirrors a user's own duty shifts into their personal Google Calendar so they do not have to copy them by hand.

Users who do not enable this feature are never asked for any Google permission and retain full use of the application.

2. OAuth scopes we request, and why

The feature runs in a separate Google Apps Script project and separate Google Cloud project (calendar-sync-app) which requests only these four scopes — exactly matching the app manifest, with nothing additional:

ScopeWhat it is used forHow it is constrained
.../auth/calendar Create, update, and delete events representing the signed-in user's own shifts, and let the user choose or create the destination calendar (e.g. a separate "Siriraj Rx Shifts" calendar so work shifts do not clutter their personal calendar) Only modifies or deletes events this app created — identified from the "shift ↔ event ID" table held in that user's own private storage · Never stores or transmits the content of any user event · Never accesses another user's calendar
.../auth/script.scriptapp Create and delete a time-based trigger in the user's own execution context, so the calendar keeps up with roster changes while the app is closed Exactly one trigger (_autoSyncTick) · User can enable/disable it at any time · Grants no access to any additional Google service
.../auth/script.external_request Outbound HTTPS to our own Firebase Realtime Database to read "this user's latest shifts" and write a small sync-acknowledgement receipt Single destination: siriraj-rx-shift-default-rtdb.asia-southeast1.firebasedatabase.app · No third-party service involved · No Google user data is ever sent out
.../auth/userinfo.email Read the email address of the Google account the user selected, so we can show which account will receive the shifts and prevent syncing into the wrong account Display and account-matching only · Never transmitted outside the system · Never used for marketing

Why calendar and not the narrower calendar.events: the feature lets the user pick an existing destination calendar or create a new dedicated one. That is calendar-level management (calendar list and calendar objects), which calendar.events cannot do. The only way to use the narrower scope would be to always write into the user's primary calendar — which is worse for user privacy, because work shifts would then be inseparable from personal events and could not be hidden or unsubscribed independently.

3. What we access, what we store, and where

DataWhere it livesWho can reach it
OAuth access / refresh tokens We never store them. Google Apps Script holds and manages them entirely within Google infrastructure. We hold no copy and have no storage for them. Nobody on our side
Shift ↔ event ID mapping, chosen destination calendar PropertiesService.getUserProperties() — per-user private storage allocated by Google and bound to that user's account Only script executions running as that user. The developer cannot read it; other users cannot reach it; no administrator API exposes it
Selected Google account email Transient memory during execution, plus that user's own PropertiesService Same as above
The user's shift list (feed) Firebase Realtime Database, region asia-southeast1 — written by the main system, read by the user's own trigger See §5.6
Sync acknowledgement (ack) Firebase, same database — counts of events created/updated/deleted plus a timestamp; no event content See §5.6

What appears in a calendar event: date · start and end time · shift type (e.g. "morning shift") · assigned unit or room. Nothing else.

What is never involved: patient data · health information (PHI/PHR) · medical record numbers · clinical records. The system is a staff scheduling tool, not a medical records system, and has never touched such data.

Data flow is one-way: app → the user's calendar. We do not touch events the app did not create, do not access calendars the user did not select, and do not pull any calendar content back into the system. During a sync, the app lists events only within the shift date range on the destination calendar, solely to verify that its own previously created events are still present — it checks only the event ID and the location field, reads no event content, and stores or transmits nothing from any other event.

4. Purpose of use, and Limited Use compliance

The data is used for exactly one purpose: reminding the user of their own work shifts in the calendar they already use daily.

Our use and transfer of information received from Google APIs adheres to the Google API Services User Data Policy, including the Limited Use requirements. Specifically we affirm that we do not:

5. Data protection measures

5.1 Encryption in transit

Every network path enforces HTTPS/TLS 1.2 or higher; no plain-HTTP path exists anywhere: user's browser ↔ Apps Script web app · Apps Script ↔ Google Calendar API · Apps Script ↔ Firebase Realtime Database (UrlFetchApp rejects invalid certificates automatically).

5.2 Encryption at rest

All data resides in Google infrastructure (Apps Script PropertiesService, Google Sheets, Firebase Realtime Database), which is encrypted at rest with AES-256 by default. We operate no servers, no databases, and no disks of our own that hold user data at any point.

5.3 Access control — the developer cannot reach users' Google data at all

This is the strongest protection in the design, and it is deliberate:

5.4 Token handling

We do not store, log, or transmit any OAuth token. Access and refresh tokens are held entirely by Google Apps Script. When a user revokes access at Google Account permissions, authorization ends immediately without requiring any action on our side.

5.5 Project isolation for least privilege

The Calendar feature was deliberately split into its own Apps Script project and its own Google Cloud project, separate from the main system. The main system (which holds higher-privilege scopes used only for administrator back-office tasks) and the Calendar project share no credentials whatsoever. A user connecting their calendar is therefore asked for exactly the four scopes in §2 and nothing from the back-office side.

5.6 Roster data in Firebase (feed / ack)

calFeed holds a user's shift list keyed by their internal display name (not an email address, not a Google ID). Its contents are the same roster information that every member of the department already sees on the shared duty roster as a matter of normal operation. calAck holds only summary counts (how many events were created/updated/deleted, and when) — no event content.

The database is in region asia-southeast1 (Singapore), encrypted at rest, and holds no data obtained from Google APIs whatsoever — no tokens, no event IDs, no calendar content.

5.7 Logging and auditability

Every script execution is recorded automatically in Google Cloud Logging (Stackdriver), as configured for the project, and each sync run writes an acknowledgement record (calAck) with a timestamp and the number of events created, updated, and deleted — so it is always auditable how many calendar changes were made and when. These records never contain event content and never contain tokens.

5.8 Retention and deletion

DataRetention
Shift ↔ event ID mappingFor as long as the user keeps the feature enabled · deleted immediately on "Disconnect"
Linked account emailSame
The user's calFeed entryHolds only the latest published version of each roster month · when a month's roster changes, that month's entry is overwritten wholesale; no edit history is kept
calAck receiptOnly the most recent record · overwritten on every sync

Pressing "Disconnect" in the app (1) deletes every event this app created from the user's calendar, (2) deletes the mappings and settings from PropertiesService, (3) deletes the installed trigger, and (4) revokes the script's authorization — all from a single button press. (If a specific event cannot be deleted at that moment — e.g. the calendar is temporarily unreachable — the user is informed, and the mapping for that one event is retained so deletion can be completed on a later attempt rather than leaving an orphaned event behind.)

5.9 Breach response

If we become aware of an incident affecting user data, we will (1) suspend the feature and revoke authorizations immediately, (2) notify affected users by email and via in-app announcement within 72 hours of becoming aware, and (3) notify Google through the designated channel if the incident involves data obtained from Google APIs.

5.10 Personnel with access

The system is built and maintained by a single developer (the contact in §9). There are no employees, no subcontractors, and no third parties with access. The developer's Google account that owns the project has 2-Step Verification enabled.

6. Third-party sharing

We share no Google API data with any third party. There are no analytics services, no trackers, no advertising, and no external CDN that receives user data. The only data processor is Google LLC, as the infrastructure provider (Apps Script, Calendar, Firebase).

7. User rights

Users have the right to access, correct, obtain a copy of, object to the processing of, and delete their data, under Thailand's Personal Data Protection Act B.E. 2562 (PDPA). All of it can be exercised immediately and without contacting us:

  1. Disconnect in-app — the "Disconnect" button on the "Calendar settings" screen deletes every event created, deletes all stored data, and removes the trigger.
  2. Delete events only, staying connected — the "Clear all shift events" button.
  3. Revoke from Google's side — at Google Account permissions, select "Siriraj Rx Shift Calendar" and remove access.
  4. Turn off automatic updates only — the "Automatic updates" toggle (removes the trigger; already synced events remain).

Deletion requests and other enquiries: the email in §9. We respond within 30 days.

8. Children

The system is used exclusively by licensed pharmacy professionals. It is not designed for or directed at anyone under 18, and we do not knowingly collect data from minors.

9. Changes to this policy, and contact

If we make material changes we will update the "Last updated" date above and notify users through an in-app announcement.

Data controller / contact: Norapol Uttho — norapol.uttho@gmail.com
App website: https://sirxshift.com/