๐Ÿš€ Secretlab Store API

A versioned key-value store built with Laravel 12 that stores JSON or string values while preserving version history. Retrieve the latest value or any historical value using a UNIX timestamp.


๐Ÿ“Œ Disclaimer


๐Ÿ“š Table of Contents


๐Ÿ“– Project Overview

This project provides a lightweight HTTP API for storing versioned key-value data.

Every successful update creates a new immutable version of the value. Previous versions are preserved, allowing historical lookups using a UNIX timestamp.

Features


Available Endpoints


๐Ÿ“‹ Requirements

No host PHP installation is required.


โšก Quick Setup

git clone https://sdatulayta@bitbucket.org/my-project/secretlab-store-api.git
cd secretlab-store-api

cp .env.example .env

composer install

./vendor/bin/sail up -d

./vendor/bin/sail artisan key:generate

./vendor/bin/sail artisan migrate --force

๐Ÿณ Step-by-Step Local Setup

1. Clone Repository

git clone https://sdatulayta@bitbucket.org/my-project/secretlab-store-api.git
cd secretlab-store-api

2. Start Docker

Ensure Docker Desktop is running.


3. Copy Environment File

cp .env.example .env

4. Install Dependencies

composer install

or

./vendor/bin/sail composer install

5. Start Laravel Sail

./vendor/bin/sail up -d

If Sail is not installed:

composer require laravel/sail --dev

./vendor/bin/sail up -d

6. Generate Application Key

./vendor/bin/sail artisan key:generate

7. Verify Database Configuration

Ensure .env contains the correct database credentials.

If modified, restart Sail.

./vendor/bin/sail down

./vendor/bin/sail up -d

8. Run Database Migrations

./vendor/bin/sail artisan migrate --force

9. Access API

Local URL

http://localhost/api/

Public URL

https://secretlab.stifd.com/api/

โš™๏ธ Environment Variables

APP_ENV=local
APP_DEBUG=true

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=secretlab
DB_USERNAME=sail
DB_PASSWORD=password

CACHE_DRIVER=array

Description


๐Ÿ—„ Database Schema

Objects

Fields

Index

INDEX (object_key, version_timestamp)

Optimizes historical lookups by key and timestamp.

Unique Constraint

UNIQUE (
    object_key,
    object_hash,
    version_timestamp
)

Prevents duplicate inserts.


๐ŸŒ API Endpoints


1. POST /api/object

Store a new version of a key.

Request

{
    "mykey": {
        "name": "Stephen"
    }
}

Rules

A-Z
a-z
0-9
_
-
.

Value cannot be

Success

201 Created

{
    "message": "created",
    "data": {
        "version_timestamp": 1670000000
    }
}

Error Responses

Test Scenarios Covered


2. GET /api/object/{key}

Returns the latest value.

Supports historical lookup.

?timestamp=1670000000

Returns the latest record where

version_timestamp <= timestamp

Success

{
    "data": {
        "name": "Version 2"
    }
}

Error Responses

Test Scenarios Covered


3. GET /api/object/get_all_records

Returns the latest value for every key.

Query Parameters

Maximum

per_page=100

Success

{
    "data": [
        {
            "key": "a",
            "value": "v2",
            "version_timestamp": 200
        },
        {
            "key": "b",
            "value": "hello",
            "version_timestamp": 150
        }
    ],
    "meta": {
        "total": 2,
        "per_page": 15,
        "current_page": 1
    }
}

Test Scenarios Covered


๐Ÿ’ก Examples

Create Object

curl -X POST http://localhost/api/object \
-H "Content-Type: application/json" \
-d '{"mykey":{"name":"Stephen"}}'

Response

{
    "message":"created",
    "data":{
        "version_timestamp":1670000000
    }
}

Get Latest

curl http://localhost/api/object/mykey
{
    "data":{
        "name":"Version 2"
    }
}

Historical Lookup

curl "http://localhost/api/object/mykey?timestamp=150"
{
    "data":"value1"
}

Get All Records

curl "http://localhost/api/object/get_all_records?per_page=5&page=1"

๐Ÿงช Testing & Coverage

Run migrations

./vendor/bin/sail artisan migrate:fresh --seed

Run tests

./vendor/bin/sail test

PHPUnit

./vendor/bin/sail php vendor/bin/phpunit --testdox

Recommended


๐Ÿ”„ CI/CD - Bitbucket Pipelines

This project uses Bitbucket Pipelines to automate continuous integration and continuous deployment.

The pipeline performs:


Continuous Integration (CI)

Every pipeline run performs automated validation by:

Example:

- step:
    name: Run Laravel Tests

    caches:
        - composer

    services:
        - mysql

    script:

        - apt-get update
        - apt-get install -y unzip git libzip-dev

        - docker-php-ext-install zip pdo_mysql

        - curl -sS https://getcomposer.org/installer | php
        - mv composer.phar /usr/local/bin/composer

        - composer install --no-interaction

        - cp .env.example .env.testing

        - sed -i 's/DB_HOST=.*/DB_HOST=localhost/' .env.testing
        - sed -i 's/DB_USERNAME=.*/DB_USERNAME=root/' .env.testing
        - sed -i 's/DB_PASSWORD=.*/DB_PASSWORD=root/' .env.testing
        - sed -i 's/DB_DATABASE=.*/DB_DATABASE=testdb/' .env.testing

        - php artisan key:generate --env=testing

        - php artisan migrate --env=testing

        - php artisan test

Continuous Deployment (CD)

Production deployment is automatically triggered after code is pushed to the main branch.

The deployment process:

Example:

- step:
    name: Deploy Production

    deployment: production

    script:
      - cat /etc/os-release
      - apt-get update
      - apt-cache policy openssh-client

      - apt-get install -y openssh-client

      - mkdir -p ~/.ssh
      - ssh-keyscan secretlab.stifd.com >> ~/.ssh/known_hosts

      - ssh username@secretlab.stifd.com "
          cd {APP_PATH} &&
          git pull origin main &&
          composer install --no-dev --optimize-autoloader &&
          php artisan optimize
        "

Deployment Trigger

Production deployment runs automatically when changes are pushed to:

main branch

Deployment flow:

Developer Push
      |
      v
Bitbucket Repository
      |
      v
CI Pipeline
      |
      |-- Install Dependencies
      |-- Run Migrations
      |-- Execute Tests
      |
      v
CD Pipeline
      |
      |-- SSH to Production Server
      |-- Pull Latest Code
      |-- Install Production Dependencies
      |-- Optimize Laravel
      |
      v
Production Environment

Recommended Improvements

For a production environment, consider adding:


โšก Performance Notes

Current optimizations

Recommendations for larger datasets


๐Ÿ›  Troubleshooting

Database Connection Errors

Verify


Tests Failing

./vendor/bin/sail artisan migrate:fresh

Ensure

CACHE_DRIVER=array

Reset Database

./vendor/bin/sail artisan migrate:fresh

๐Ÿ“ Project Files of Interest

routes/api.php

app/Http/Requests/StoreObjectRequest.php

app/Http/Controllers/Api/ObjectController.php

app/Services/ObjectService.php

app/Repositories/ObjectRepository.php

app/Models/KeyValue.php

database/migrations/2026_07_15_222701_create_objects_table.php

tests/Feature/ObjectApiTest.php

๐Ÿ›  Built With


๐Ÿ“„ License

This project was created solely for the Secretlab Technical Exercise.

It is intended for evaluation purposes only.


API Testing

To test the API quickly, please download the provided Postman collection.

๐Ÿ“ฅ Download Postman Collection

Import the collection into Postman