diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fd93906507473de899ad3de720b81bdd17c1ba99..5ca75d58467966d5f55f88f9642554907248f883 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,8 +16,8 @@ install_test:
   stage: install_test
   image: "europe-north1-docker.pkg.dev/holi-shared/docker-hub-remote/python:3.12-slim"
   script:
-    - pip install -r src/requirements.txt
-    - pip install -r src/dev-requirements.txt
+    - pip install -r requirements.txt
+    - pip install -r dev-requirements.txt
     - pytest
   interruptible: true
 
@@ -38,10 +38,7 @@ install_test:
     ENVIRONMENT_ID: $CI_ENVIRONMENT_SLUG
   script:
     - apk add zip
-    - mkdir build
-    - cd src
-    - zip -r ../build/search_integration.zip ./*
-    - cd ..
+    - zip -r search_integration.zip requirements.zip dev-requirements.zip *.py
     - terraform/environments/scripts/create-or-update-env.sh "$ENVIRONMENT_ID" "$CI_COMMIT_SHA"
   interruptible: false
 
diff --git a/src/__init__.py b/__init__.py
similarity index 100%
rename from src/__init__.py
rename to __init__.py
diff --git a/src/dev-requirements.txt b/dev-requirements.txt
similarity index 100%
rename from src/dev-requirements.txt
rename to dev-requirements.txt
diff --git a/main.py b/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..fcb17e59a987512c08c226762056aeff804e2c2a
--- /dev/null
+++ b/main.py
@@ -0,0 +1,53 @@
+import base64
+import json
+
+import functions_framework
+from cloudevents.http.event import CloudEvent
+from dataclasses import dataclass
+
+@dataclass
+class UserPayload:
+    id: str
+    name: str
+    email: str
+    identity: str
+    avatar: str
+
+    def __init__(self, data: dict):
+        print(f"UserPayload: {data}")
+        self.id = data['user']['id']
+        self.name = data['user']['name']
+        self.email = data['user']['email']
+        self.identity = data['user']['identity']
+        self.avatar = data['user']['avatar']
+
+
+@dataclass
+class UserNameUpdatedEvent(UserPayload):
+    event_type: str
+    event_version: str
+
+    def __init__(self, event: CloudEvent):
+        message = event['data']['message']
+        if message['attributes']['eventType'] != 'UserNameUpdated':
+            raise ValueError(f'Expected event of type UserNameUpdated, got {data['eventType']}')
+        self.event_type = message['attributes']['eventType']
+        self.event_version = message['attributes']['eventVersion']
+        super().__init__(json.loads(decode_message_data(message['data'])))
+
+
+def process_user_name_updated_event(event: UserNameUpdatedEvent):
+    print(f'process_user_name_updated_event: {event}')
+
+def decode_message_data(data: str):
+    return base64.b64decode(data)
+
+def process_event(event: CloudEvent):
+    attributes = event['data']['message']['attributes']
+    if attributes['eventType'] == 'UserNameUpdated' and attributes['eventVersion'] == '1.0.0': # TODO backwards semver
+        process_user_name_updated_event(UserNameUpdatedEvent(event))
+
+@functions_framework.cloud_event
+def process_message(cloud_event: CloudEvent):
+    print(f"Received message: {cloud_event}")
+    process_event(cloud_event)
diff --git a/src/requirements.txt b/requirements.txt
similarity index 100%
rename from src/requirements.txt
rename to requirements.txt
diff --git a/src/main.py b/src/main.py
deleted file mode 100644
index 6d8ad33854169070fa11e1403c1a4574b01ce174..0000000000000000000000000000000000000000
--- a/src/main.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import base64
-import functions_framework
-
-@functions_framework.cloud_event
-def process_message(cloud_event):
-    # TODO remove inspection prints
-    print(f"Received message: {cloud_event}")
-    if 'data' in cloud_event:
-        message = base64.b64decode(event['data']).decode('utf-8')
-        print(f"Received message: {message}")
-    else:
-        print("No data found in event.")
diff --git a/src/test_main.py b/src/test_main.py
deleted file mode 100644
index c862d605e76258a0096db1c9791270e2e4ea353f..0000000000000000000000000000000000000000
--- a/src/test_main.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-def test_process_message():
-    pass
\ No newline at end of file
diff --git a/terraform/environments/function.tf b/terraform/environments/function.tf
index 4881eaf2a3718d648f94173156aa405c1dcb0999..9bc1683a17e3830d8f812ec942064657fa4f876e 100644
--- a/terraform/environments/function.tf
+++ b/terraform/environments/function.tf
@@ -8,7 +8,7 @@ resource "random_id" "main" {
 resource "google_storage_bucket_object" "function_source" {
   name   = "${random_id.main.hex}/search_integration.zip"
   bucket = data.terraform_remote_state.holi_infra_state.outputs.gcf_sources_upload_bucket_name
-  source = "../../build/search_integration.zip"
+  source = "../../search_integration.zip"
 }
 
 resource "google_cloudfunctions2_function" "holi-search-integration" {
diff --git a/test_main.py b/test_main.py
new file mode 100644
index 0000000000000000000000000000000000000000..57e197a37396bf88afc19d168bd988dd12f726f8
--- /dev/null
+++ b/test_main.py
@@ -0,0 +1,32 @@
+from main import process_message
+
+event = {
+    'attributes':
+        {
+            'id': '12833783708309476',
+            'time': '2024-12-07T16:21:48.022Z',
+            'specversion': '1.0',
+            'datacontenttype': 'application/json',
+            'type': 'google.cloud.pubsub.topic.v1.messagePublished',
+            'source': '//pubsub.googleapis.com/'
+        },
+    'data': {
+        'message': {
+            '@type': 'type.googleapis.com/google.pubsub.v1.PubsubMessage',
+            'data': 'eyJ1c2VyIjogeyJpZCI6ICIxNDlhM2QyOS1hMGRhLTRmNTItOGUxYy02NjAzNzZiNzA4NGIiLCAibmFtZSI6ICJEYW5pZWwgaG9saSB0ZWFtIiwgImVtYWlsIjogImRhbmllbEBob2xpLnRlYW0iLCAiaWRlbnRpdHkiOiAiZGFuaWVsaG9saS50ZWFtIiwgImF2YXRhciI6ICJodHRwczovL2lrLmltYWdla2l0LmlvL2hvbGkvX0RFVl8vYXZhdGFyLzE0OWEzZDI5LWEwZGEtNGY1Mi04ZTFjLTY2MDM3NmI3MDg0Yl95djMxVVc3bEQwLmpwZyJ9fQ==',
+            'attributes': {
+                'eventType': 'UserNameUpdated',
+                'eventVersion': '1.0.0'
+            },
+            'messageId': '12833783708309476',
+            'publishTime': '2024-12-07T16:21:48.022Z'
+        }
+    }
+}
+
+def test_process_message():
+    process_message(event)
+
+
+if __name__ == '__main__':
+    test_process_message()
\ No newline at end of file