Project 03 · Integration · Data Control
One Source of Truth Across Three Clouds
Many teams keep the same information in three places — Microsoft 365, Google Workspace, and Notion — and the three never quite match. I built a Python tool that keeps them in sync as one trusted source of truth: it decides who can see what, keeps each file in its proper place, and records every change so it can be checked later.
01 The problem: the truth is in three places
Most teams do not have too little information. They have the same information spread across too many apps. The real version of a record is in one place, its files are in another, and the work around it happens in a third. Nobody can answer one simple question: "Where is the correct version, and who is allowed to see it?"
The obvious fix — copy everything into one app — is the wrong move when the data is private or sensitive. Every copy is one more place that can leak. And some files are not allowed to move: rules may say they must stay in a certain account, region, or service. So the challenge was to give people the feeling of one single source of truth, while letting each piece of data stay exactly where the rules say it must.
Files are linked, never copied or moved. The main record keeps a tidy row of information plus a link to the real file in its home app. So there is only one copy of any sensitive file, in its proper place, and the tool only adds links and notes — it never makes extra copies.
02 How it is built: one hub, many connectors
The design is simple. Notion is the hub — the main, easy-to-read record that people look at. Each other app (Microsoft 365, Google Workspace) has its own small connector. A connector does four things: log in, get what changed, put it into one shared format, and note where the data is allowed to live. A central part then keeps every app in step with the hub on a schedule, and a control layer wraps the whole thing.
Log in
Each app connects with its own secure login and the smallest access it needs.
Get changes
It pulls only what changed since last time, so it stays fast.
Tidy up
It puts every app's data into one shared format and tags where it must live.
Match
It updates the hub by a fixed ID, and links files instead of copying them.
Log
It writes down every change so it can be checked later.
# Every app follows the same simple shape. Adding a new app # means writing one small class — nothing else has to change. class Connector: name = "" lives_in = "" # where this data is allowed to live def log_in(self): ... def get_changes(self, since): ... # only what changed def to_common_format(self, item): ... def link_for(self, item): ... # a link — we never copy the file
03 One record, never a duplicate
The biggest risk in a sync tool is the duplicate. Run it twice and you get two of everything. I stop this by giving every record a fixed ID built from its own details. Then syncing is simple: if that ID is already in the hub, update it; if not, add it. Running the whole tool again always ends in one correct result — no copies.
import hashlib def fixed_id(app, kind, original_id): # Same details always give the same ID. So records never duplicate. text = f"{app}|{kind}|{original_id}".lower().strip() return "FQ-" + hashlib.sha1(text.encode()).hexdigest()[:16] def sync_one(record, hub): key = fixed_id(record.app, record.kind, record.original_id) if hub.has(key): hub.update(key, record.changed_fields()) # keep human notes safe else: hub.add(key, record.fields())
The tool only updates the fields it owns — values, sync dates, and links. It never overwrites notes that a person wrote by hand. So the automatic updates and the human notes live side by side without fighting.
04 Control: who can see it, and where it lives
Bringing data together is only safe if you also bring the rules together. The control layer adds two checks to every record:
| Control | What it does | How |
|---|---|---|
| Who can see what | Sets read/write rights per type of record | A role-to-permission list is checked before any read or write |
| Where data lives | Keeps each record and file in its allowed place | Each record carries a fixed "lives in" tag; moves out of bounds are refused |
| Which app wins | Decides the main app when two disagree | A main/backup order, so a backup can add to but not replace the main |
| Least access | Limits what each connector can touch | Each connector only gets access to the exact data it needs |
Because files are linked and not copied, a file that must stay in one place physically never leaves it. The hub just holds a link, and the rules decide who may open it. This is the same careful, "keep data where it belongs" approach that strict environments need — and it is exactly what data-protection laws like GDPR and KVKK are asking for.
05 Checking the work and keeping a safe record
A tool that controls data must be able to show what it did. After each sync, it counts the records and checks the totals before calling the run a success. And it writes every action to a safe, add-only log where each entry includes a code from the entry before it. If anyone tries to change the history later, the codes stop matching and the change is easy to spot.
import hashlib, json def add_to_log(log, action): last = log[-1]["code"] if log else "START" text = json.dumps(action, sort_keys=True) code = hashlib.sha256(f"{last}{text}".encode()).hexdigest() log.append({"action": action, "after": last, "code": code}) return log # change any old entry and every later code breaks
- Count and total checks after each run — the run only passes if the numbers add up.
- A safe history that proves the record of changes has not been edited later.
- A preview mode that shows every add, update, and link before anything touches a live system — easy to review and safe to demo.
06 Why this matters
The same design that brings a company's apps together is also the design that careful, regulated work needs: one clear main record, connectors that respect each app's limits, fixed IDs so nothing leaks or duplicates, and a record you can check. It is the everyday-business version of the strict separation work I did for US government projects — and it shows, in real Python code, the "keep data where it belongs and control who sees it" approach that GDPR and KVKK are built around.
Want your apps to agree on one truth?
I build sync tools that feel like one system without breaking the rules.
[email protected]