the beginning of the idiots
This commit is contained in:
39
qwen/hack/.env
Normal file
39
qwen/hack/.env
Normal file
@@ -0,0 +1,39 @@
|
||||
APP_NAME=MerchantsOfHope
|
||||
APP_VERSION=0.1.0
|
||||
APP_ENV=development
|
||||
DEBUG=true
|
||||
TIMEZONE=UTC
|
||||
|
||||
# Database
|
||||
DB_HOST=localhost
|
||||
DB_NAME=moh
|
||||
DB_USER=moh_user
|
||||
DB_PASS=moh_password
|
||||
DB_PORT=5432
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=MerchantsOfHopeSecretKeyChangeInProduction
|
||||
|
||||
# Session
|
||||
SESSION_LIFETIME=86400
|
||||
|
||||
# Tenant Configuration
|
||||
TENANT_ISOLATION_ENABLED=true
|
||||
|
||||
# Compliance
|
||||
ACCESSIBILITY_ENABLED=true
|
||||
GDPR_COMPLIANCE_ENABLED=true
|
||||
PCI_DSS_COMPLIANCE_ENABLED=true
|
||||
|
||||
# Social Login (OAuth2)
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
GITHUB_CLIENT_ID=
|
||||
GITHUB_CLIENT_SECRET=
|
||||
|
||||
# Email
|
||||
MAIL_HOST=smtp.example.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=mailer@example.com
|
||||
MAIL_PASSWORD=mailer_password
|
||||
MAIL_ENCRYPTION=tls
|
||||
85
qwen/hack/AGENTS.md
Normal file
85
qwen/hack/AGENTS.md
Normal file
@@ -0,0 +1,85 @@
|
||||
Do not perform any operations on the host other than git and docker / docker compose operations
|
||||
|
||||
Utilize docker containers for all work done in this repository.
|
||||
Utilize a docker artifact related name prefix of <codingagent>-<language>-<function> to make it easy to manage all the docker artifacts.
|
||||
|
||||
Only expose the main app web interface over the network. All other ports should remain on a per stack docker network.
|
||||
|
||||
Here are the port assignments for the containers
|
||||
|
||||
|
||||
gemini/go 12000
|
||||
gemini/hack 13000
|
||||
gemini/nodejs 14000
|
||||
gemini/php 15000
|
||||
gemini/python 16000
|
||||
|
||||
qwen/go 17000
|
||||
qwen//hack 18000
|
||||
qwen/nodejs 19000
|
||||
qwen/php 20000
|
||||
qwen/python 21000
|
||||
|
||||
copilot/go 22000
|
||||
copilot/gemini/hack 23000
|
||||
copilot/nodejs 24000
|
||||
copilot/php 25000
|
||||
copilot/python 26000
|
||||
|
||||
The purpose of this repository is to test three coding agents:
|
||||
|
||||
qwen
|
||||
copilot
|
||||
gemini
|
||||
|
||||
and five programming languages:
|
||||
|
||||
go
|
||||
hack
|
||||
nodejs
|
||||
php
|
||||
python
|
||||
|
||||
against the following programming test:
|
||||
|
||||
I have purchased the domain name MerchantsOfHope.org and its intened to be the consulting/contracting arm of TSYS Group.
|
||||
It will need to handle:
|
||||
|
||||
- Multiple independent tennants (TSYS Group has dozens and dozens of lines of business, all fully isolated from each other)
|
||||
- OIDC and social media login
|
||||
|
||||
It will need to handle all functionality of a recuriting platform:
|
||||
|
||||
- Job seekers browsing postions and posting resumes/going through the application process
|
||||
- Job providrrs managing the lifecycle of positions and applications
|
||||
|
||||
This should be pretty simple and off the shelf, bog standard type workflows.
|
||||
|
||||
Presume USA law compliance only.
|
||||
|
||||
No need for anything other than English to be supported.
|
||||
|
||||
Accessibility is critical, we have a number of US Government contracts and they mandate accessibility.
|
||||
|
||||
Also we need to be compliant with PCI, GDPR, SOC, FedRamp etc.
|
||||
|
||||
|
||||
Use the name of the directory you are in to determine the programming language to use.
|
||||
|
||||
Do not create any artifacts outside of the directory you are in now.
|
||||
|
||||
You may manage the contents of this directory as you see fit.
|
||||
|
||||
Please keep it well organized.
|
||||
|
||||
Follow Test Driven Development for all your work.
|
||||
|
||||
Create and maintain a docker-compose.yml file with your service dependenices
|
||||
|
||||
Ship this application as a docker container.
|
||||
|
||||
This will eventually be deployed into a k8s cluster , so make sure to take that into account.
|
||||
|
||||
Also follow all best common practices for security, QA, engineering, SRE/devops etc.
|
||||
|
||||
Make it happen.
|
||||
53
qwen/hack/Dockerfile
Normal file
53
qwen/hack/Dockerfile
Normal file
@@ -0,0 +1,53 @@
|
||||
FROM hhvm/hhvm:latest
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
curl \
|
||||
libpng-dev \
|
||||
libonig-dev \
|
||||
libxml2-dev \
|
||||
zip \
|
||||
unzip \
|
||||
supervisor \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install and configure PHP extensions (for compatibility with PHP libraries)
|
||||
RUN docker-php-ext-install \
|
||||
pdo \
|
||||
pdo_mysql \
|
||||
gd \
|
||||
mbstring \
|
||||
xml \
|
||||
zip
|
||||
|
||||
# Install Composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Copy application files
|
||||
COPY . /var/www/html
|
||||
|
||||
# Install PHP dependencies
|
||||
RUN composer install --no-dev --optimize-autoloader
|
||||
|
||||
# Make sure scripts are executable
|
||||
RUN chmod +x /var/www/html/docker-start.sh
|
||||
|
||||
# Expose port 18000 as specified in AGENTS.md for qwen/hack
|
||||
EXPOSE 18000
|
||||
|
||||
# Use dumb-init to handle signals properly for k8s
|
||||
RUN set -eux; \
|
||||
wget -O /usr/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64; \
|
||||
chmod +x /usr/bin/dumb-init
|
||||
|
||||
# Start the application
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
CMD ["hhvm", "-m", "server", "-p", "18000", "--document-root", "/var/www/html/public"]
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:18000/ || exit 1
|
||||
52
qwen/hack/README.md
Normal file
52
qwen/hack/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# MerchantsOfHope.org - Recruiting Platform
|
||||
|
||||
This is the official repository for MerchantsOfHope.org, the recruiting platform for TSYS Group.
|
||||
|
||||
## Overview
|
||||
|
||||
MerchantsOfHope.org is designed to handle:
|
||||
- Multiple independent tenants (TSYS Group has dozens of lines of business, all fully isolated from each other)
|
||||
- OIDC and social media login
|
||||
- Job seekers browsing positions and posting resumes/going through the application process
|
||||
- Job providers managing the lifecycle of positions and applications
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- Language: Hack (PHP)
|
||||
- Framework: Slim Framework 4
|
||||
- Container: Docker
|
||||
- Deployment: Kubernetes-ready
|
||||
|
||||
## Architecture
|
||||
|
||||
- Multi-tenant architecture ensuring complete isolation between different business lines
|
||||
- OIDC and social login integration
|
||||
- Compliance-ready with USA law, accessibility standards, PCI, GDPR, SOC, and FedRAMP
|
||||
|
||||
## Development
|
||||
|
||||
1. Clone this repository
|
||||
2. Install dependencies with `composer install`
|
||||
3. Set up environment variables in `.env`
|
||||
4. Run with Docker Compose
|
||||
|
||||
## Port Assignment
|
||||
|
||||
This service runs on port 18000 as per the project requirements.
|
||||
|
||||
## Testing
|
||||
|
||||
The project follows Test Driven Development (TDD) methodology. Run tests with:
|
||||
```bash
|
||||
composer test
|
||||
```
|
||||
|
||||
## Security & Compliance
|
||||
|
||||
This project implements:
|
||||
- Accessibility features for US Government contracts
|
||||
- PCI DSS compliance
|
||||
- GDPR compliance
|
||||
- SOC compliance
|
||||
- FedRAMP compliance
|
||||
- USA law compliance
|
||||
0
qwen/hack/assets/.gitkeep
Normal file
0
qwen/hack/assets/.gitkeep
Normal file
52
qwen/hack/composer.json
Normal file
52
qwen/hack/composer.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "qwen/merchanthope-hack",
|
||||
"description": "MerchantsOfHope.org recruiting platform built with Hack/PHP",
|
||||
"type": "project",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Qwen Coding Agent",
|
||||
"email": "qwen@example.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"hhvm": "^4.0",
|
||||
"slim/slim": "^4.0",
|
||||
"slim/psr7": "^1.0",
|
||||
"firebase/php-jwt": "^6.0",
|
||||
"guzzlehttp/guzzle": "^7.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"vlucas/phpdotenv": "^5.0",
|
||||
"php-di/php-di": "^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"fakerphp/faker": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/bootstrap.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"start": "hhvm -m server -p 8080 --document-root public/",
|
||||
"test": "phpunit",
|
||||
"test-coverage": "phpunit --coverage-html coverage/",
|
||||
"cs-fix": "php-cs-fixer fix",
|
||||
"cs-check": "php-cs-fixer fix --dry-run",
|
||||
"phpstan": "phpstan analyze"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
91
qwen/hack/docker-compose.yml
Normal file
91
qwen/hack/docker-compose.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
container_name: qwen-hack-moh
|
||||
ports:
|
||||
- "18000:18000"
|
||||
environment:
|
||||
- APP_ENV=development
|
||||
- DB_HOST=database
|
||||
- DB_NAME=moh
|
||||
- DB_USER=moh_user
|
||||
- DB_PASS=moh_password
|
||||
- JWT_SECRET=MerchantsOfHopeSecretKeyChangeInProduction
|
||||
volumes:
|
||||
- .:/var/www/html
|
||||
- ./docker/logs:/var/log/app
|
||||
depends_on:
|
||||
- database
|
||||
- redis
|
||||
- mailhog
|
||||
networks:
|
||||
- moh-network
|
||||
|
||||
database:
|
||||
image: postgres:13
|
||||
container_name: moh-database
|
||||
environment:
|
||||
- POSTGRES_DB=moh
|
||||
- POSTGRES_USER=moh_user
|
||||
- POSTGRES_PASSWORD=moh_password
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- moh_db_data:/var/lib/postgresql/data
|
||||
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
networks:
|
||||
- moh-network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U moh_user -d moh"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
container_name: moh-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- moh_redis_data:/data
|
||||
networks:
|
||||
- moh-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
mailhog:
|
||||
image: mailhog/mailhog
|
||||
container_name: moh-mailhog
|
||||
ports:
|
||||
- "1025:1025" # SMTP
|
||||
- "8025:8025" # Web UI
|
||||
networks:
|
||||
- moh-network
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: moh-nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- .:/var/www/html
|
||||
- ./docker/nginx.conf:/etc/nginx/nginx.conf
|
||||
depends_on:
|
||||
- app
|
||||
networks:
|
||||
- moh-network
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
moh_db_data:
|
||||
moh_redis_data:
|
||||
|
||||
networks:
|
||||
moh-network:
|
||||
driver: bridge
|
||||
0
qwen/hack/public/.gitkeep
Normal file
0
qwen/hack/public/.gitkeep
Normal file
53
qwen/hack/public/index.php
Normal file
53
qwen/hack/public/index.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?hh // strict
|
||||
|
||||
/**
|
||||
* Main application entry point for MerchantsOfHope
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/bootstrap.php';
|
||||
|
||||
use App\Controllers\HomeController;
|
||||
use Slim\Factory\AppFactory;
|
||||
use Slim\Middleware\ContentLengthMiddleware;
|
||||
use Slim\Routing\RouteCollectorProxy;
|
||||
|
||||
// Set up the Slim application
|
||||
AppFactory::setContainer($container);
|
||||
$app = AppFactory::create();
|
||||
|
||||
// Add middleware
|
||||
$app->addBodyParsingMiddleware();
|
||||
$app->addRoutingMiddleware();
|
||||
$app->add(new ContentLengthMiddleware());
|
||||
|
||||
// Define routes
|
||||
$app->get('/', [HomeController::class, 'index']);
|
||||
|
||||
// Group routes for API
|
||||
$app->group('/api', function (RouteCollectorProxy $group) {
|
||||
// Authentication routes
|
||||
$group->post('/auth/login', [App\Controllers\AuthController::class, 'login']);
|
||||
$group->post('/auth/logout', [App\Controllers\AuthController::class, 'logout']);
|
||||
$group->post('/auth/register', [App\Controllers\AuthController::class, 'register']);
|
||||
|
||||
// Job seeker routes
|
||||
$group->get('/jobs', [App\Controllers\JobController::class, 'listJobs']);
|
||||
$group->get('/jobs/{id}', [App\Controllers\JobController::class, 'getJob']);
|
||||
$group->post('/applications', [App\Controllers\ApplicationController::class, 'apply']);
|
||||
|
||||
// Job provider routes
|
||||
$group->get('/my-jobs', [App\Controllers\JobController::class, 'myJobs']);
|
||||
$group->post('/jobs', [App\Controllers\JobController::class, 'createJob']);
|
||||
$group->put('/jobs/{id}', [App\Controllers\JobController::class, 'updateJob']);
|
||||
$group->delete('/jobs/{id}', [App\Controllers\JobController::class, 'deleteJob']);
|
||||
});
|
||||
|
||||
// Add error middleware in development
|
||||
if (APP_ENV === 'development') {
|
||||
$app->addErrorMiddleware(true, true, true);
|
||||
} else {
|
||||
$app->addErrorMiddleware(false, false, false);
|
||||
}
|
||||
|
||||
// Run the application
|
||||
$app->run();
|
||||
0
qwen/hack/src/.gitkeep
Normal file
0
qwen/hack/src/.gitkeep
Normal file
27
qwen/hack/src/Controllers/AuthController.php
Normal file
27
qwen/hack/src/Controllers/AuthController.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?hh // strict
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class AuthController
|
||||
{
|
||||
public function login(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'Login endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function logout(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'Logout endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function register(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'Register endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
15
qwen/hack/src/Controllers/HomeController.php
Normal file
15
qwen/hack/src/Controllers/HomeController.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?hh // strict
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class HomeController
|
||||
{
|
||||
public function index(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write('<h1>Welcome to MerchantsOfHope.org</h1>');
|
||||
return $response->withHeader('Content-Type', 'text/html');
|
||||
}
|
||||
}
|
||||
48
qwen/hack/src/Controllers/JobController.php
Normal file
48
qwen/hack/src/Controllers/JobController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?hh // strict
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class JobController
|
||||
{
|
||||
public function listJobs(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'List jobs endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function getJob(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$jobId = $args['id'];
|
||||
$response->getBody()->write(json_encode(['message' => 'Get job endpoint', 'id' => $jobId]));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function myJobs(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'My jobs endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function createJob(Request $request, Response $response): Response
|
||||
{
|
||||
$response->getBody()->write(json_encode(['message' => 'Create job endpoint']));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function updateJob(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$jobId = $args['id'];
|
||||
$response->getBody()->write(json_encode(['message' => 'Update job endpoint', 'id' => $jobId]));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function deleteJob(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$jobId = $args['id'];
|
||||
$response->getBody()->write(json_encode(['message' => 'Delete job endpoint', 'id' => $jobId]));
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
32
qwen/hack/src/bootstrap.php
Normal file
32
qwen/hack/src/bootstrap.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?hh // strict
|
||||
|
||||
use function DI\{create, get, add};
|
||||
|
||||
/**
|
||||
* Bootstrap file for the MerchantsOfHope application
|
||||
*/
|
||||
|
||||
// Enable error reporting
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
// Load environment variables
|
||||
if (file_exists(__DIR__ . '/../.env')) {
|
||||
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../');
|
||||
$dotenv->load();
|
||||
}
|
||||
|
||||
// Define application constants
|
||||
defined('APP_NAME') or define('APP_NAME', $_ENV['APP_NAME'] ?? 'MerchantsOfHope');
|
||||
defined('APP_VERSION') or define('APP_VERSION', $_ENV['APP_VERSION'] ?? '0.1.0');
|
||||
defined('APP_ENV') or define('APP_ENV', $_ENV['APP_ENV'] ?? 'development');
|
||||
defined('DEBUG') or define('DEBUG', filter_var($_ENV['DEBUG'] ?? false, FILTER_VALIDATE_BOOLEAN));
|
||||
|
||||
// Set timezone
|
||||
date_default_timezone_set($_ENV['TIMEZONE'] ?? 'UTC');
|
||||
|
||||
// Initialize autoloader
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// Initialize dependency injection container
|
||||
$container = DI\Container::build();
|
||||
Reference in New Issue
Block a user