MIT lisansı Açık kaynak v0.2 PHP 8.3+ 5253 sayılı Dernekler Kanunu uyumlu

Genel kurullarda
kağıt pusulayı
tarihe gömün.

Türk dernekleri için kriptografik doğrulamalı, açık kaynak dijital seçim yönetim sistemi. Her oy bir hash, her makbuz bir mühür. Kimse kimin kime oy verdiğini göremez — teknik olarak.

Kodu incele → Nasıl çalışır
Oyla — Divan Paneli

Kâğıt seçimin dört büyük sorunu.

Dernek genel kurullarında seçim yapmış herkes bu durumlardan en az birini yaşamıştır.

01

Saatler süren sayım

200 üyeli bir dernekte tek kurul için sayım 1–2 saat, üç kurul için gece yarısına kadar uzar. Oyla ile sayım anında biter.

02

İtiraz riski

Elle sayımda pusulalar yanlış okunabilir, sayılar tutmayabilir, mükerrer oy çıkabilir. Oyla'da her oy kriptografik hash ile kayıt altında — manipülasyon imkânsız.

03

Oy gizliliği tedirginliği

Küçük derneklerde üyeler oylarının gizli kalmadığından endişe duyar. Kimlik bilgisi ile oy bilgisi ayrı tablolarda — birbirleriyle hiçbir şekilde eşleştirilemez.

04

Tutanak derdi

Seçim biter, sonuçlar elle tutanağa geçirilir, divan imzalar. Oyla'da seçim kapandığı anda resmi tutanak PDF olarak otomatik üretilir.

Seçim günü nasıl işler.

Hazırlıktan tutanağa altı adım. Her adımda farklı bir kullanıcı rolü devreye girer.

ADIM 01 — YÖNETİCİ

Seçimi hazırla.

Üye listesini sisteme yükle — tek tek veya CSV ile toplu aktarım. Seçim kurullarını tanımla: Yönetim Kurulu, Denetleme Kurulu, Disiplin Kurulu. Adayları ilgili kurullara ata. Kota ve yedek sayısını belirle.

Oy Pusulası Yönetimi
ADIM 02 — DİVAN

Divan kurulunu oluştur, seçimi başlat.

Genel kurul açılışında divan başkanı, üyeleri ve kâtip tanımlanır. Tüm ön koşullar karşılandıktan sonra "Seçimi Başlat" ile sistem aktife alınır. Divan, hazirun sayısını ve katılım oranını canlı takip eder.

Divan — Seçim Açık
ADIM 03 — GÖREVLİ

Masada kimlik doğrula, token gönder.

Üye masaya gelir, kimliğini gösterir. Görevli TC veya sicil numarasını girer, üye bulunur, 1. imza atılır. Sistem üyeye özel tek kullanımlık oy bağlantısını SMS ile gönderir. Üye masadan ayrılmadan oyunu kullanır, görevli 2. imzayı atar.

Görevli Masası
ADIM 04 — ÜYE

Telefonundan oy kullan.

Üye SMS'teki bağlantıyı açar. Her kurul için aday listesi görüntülenir, kontenjan kadar seçim yapılır. "Oyumu Gönder ve Kilitle" ile oy kaydedilir — geri alınamaz. SMS ile makbuz kodu iletilir.

Oy Kullanma
ADIM 05 — SALON

Sonuçlar canlı akıyor.

Salon ekranına yansıtılan sonuç ekranı oylar geldikçe güncellenir. Kazananlar yeşil, yedekler açık yeşil. Seçim kapanınca ekran "Resmi Sonuçlar" moduna geçer. Projeksiyon için perde modu tam ekran açılabilir.

Canlı Sonuçlar
ADIM 06 — DİVAN

PDF tutanağı al, seçimi kapat.

Seçim kapandığı anda resmi PDF tutanağı hazır: divan kurulu, katılım istatistikleri, kurul bazlı sonuçlar, güvenlik özeti ve imza alanları. Şeffaflık için commitment hash listesi CSV olarak indirilebilir.

Katılım Raporu

Her rol için ayrı bir panel.

Admin, divan başkanı, görevli ve üye — her kullanıcı sadece kendi görevi için tasarlanmış arayüzü görür.

Her oy bir hash. Her makbuz bir mühür.

Anonimlik tasarım seviyesinde garanti altında. Teknik bir tercih değil, mimari bir zorunluluk.

Token Güvenliği

HMAC-SHA256 ile üretilen token'lar veritabanında asla plaintext olarak tutulmaz. Yalnızca hash'i saklanır. Token bir kez kullanılınca atomik olarak yakılır.

Commitment Hash

HKDF+HMAC v1 şeması: oy verisi, HKDF türetilmiş anahtar ile HMAC'lanır. Hash, oy içeriğini açıklamadan bağımsız doğrulama imkânı sunar.

Anonimlik Garantisi

votes tablosunda member_id sütunu yoktur. tokens ve votes tabloları hiçbir zaman JOIN yapılmaz. Görevli dahil hiç kimse kimin kime oy verdiğini göremez.

Tamper-Evident Log

Aktivite logu HMAC prev_hash zinciri ile korunur. Tek bir satır değişse zincir kırılır. Admin zinciri tek tıkla doğrulayabilir.

Rate Limiter

DB destekli, IP+endpoint bazlı, üstel geri çekilme ile. Session bazlı atlatma açığı kapalı. Kalıcı blok mekanizması mevcut.

Güvenlik Başlıkları

CSP, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy. Bootstrap Icons dahil tüm varlıklar self-hosted — CDN bağımlılığı yok.

Token Üretimi → HMAC-SHA256(üye_id + zaman + TOKEN_SECRET) Plaintext token sadece SMS/QR'da; veritabanında yalnızca hash Oy Kaydı → HKDF+HMAC v1: commitment = HMAC(HKDF(token+secret), oy+tuz) Anonimlik → member_id ASLA votes tablosuna yazılmaz; JOIN mümkün değil Çift Oy Engeli → Atomic token burn — PDO transaction: oy yaz + token sil Doğrulama → Üye makbuz kodu ile bağımsız teyit edebilir Şeffaflık → Seçim kapanınca commitment hash listesi CSV olarak indirilebilir Audit Log → HMAC prev_hash zinciri — tek satır değişse zincir kırılır

Sade, bağımlılıksız, test edilmiş.

Framework yok. Büyük ORM yok. Her bağımlılık bir gerekçeye dayanıyor.

BACKEND

  • PHP 8.3+ — saf MVC, framework yok
  • MariaDB 10.6+ — PDO, prepared statements
  • Composer — bağımlılık yönetimi

FRONTEND

  • Bootstrap 5.3 — temel grid ve bileşenler
  • Vanilla JS — framework yok
  • Source Serif 4 + IBM Plex Sans — tipografi
  • Bootstrap Icons — self-hosted

SERVISLER

  • TCPDF — PDF tutanak
  • Netgsm API — SMS (mock modu)
  • endroid/qr-code — QR üretimi
  • ramsey/uuid — token kimliği

ALT YAPI

  • Docker — Nginx + PHP-FPM + MariaDB
  • GitHub Actions — CI/CD pipeline
  • PHPUnit 10.5 — 73 test, 336 assertion
  • PHPStan seviye 5 — statik analiz

Ne değil.

Her yazılımın sınırı olmalı. Bu sınırlar bilinçli tercihler.

Uzaktan / online oy kullanma aracı değildir. Üye fiziksel olarak genel kurulda hazır bulunmalı, kimliğini görevliye ibraz etmelidir. Bu, Dernekler Kanunu'nun "şahsen oy kullanma" şartını karşılayan kasıtlı bir tasarım tercihidir.

Ticari bir SaaS değildir. Abonelik, bulut hesabı veya ücret yok. Kodu alır, kendi sunucuna kurarsın. MIT lisanslı, kaynak kod tamamen açık.

Her tür oylama için değildir. Dernek genel kurul organ seçimleri için tasarlandı. Anket, referandum veya genel amaçlı oylama platformu değildir.

E-Devlet veya merkezi sistem bağlantısı yoktur. TC kimlik doğrulaması görevli üzerinden fiziksel kimlik ibrazıyla yapılır; NVI API veya merkezi kimlik doğrulama entegrasyonu mevcut değildir.

Plug-and-play değildir. Kurulum teknik bilgi gerektirir: Docker, Linux komut satırı, DNS yapılandırması. Sıfır teknik bilgiyle kurulum desteklenmez.

Beş komut, çalışır halde.

Docker yeterli. Geliştirme ortamı için beş komut, production için birkaç ek adım.

GELİŞTİRME

$ git clone https://github.com/barisozyurt/oyla.git && cd oyla
$ cp .env.example .env
$ bin/install          # secret üretir, admin parolası sorar, demo veri yükler
$ docker compose up -d
$ docker compose exec php bin/migrate

PRODUCTION

$ cp .env.example .env  # APP_ENV=production, APP_DEBUG=false
$ bin/install --no-demo # demo verisi olmadan
$ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
$ docker compose exec php composer install --no-dev --optimize-autoloader
$ docker compose exec php bin/migrate

Konuşalım.

Projeyle ilgili sorularınız, hata bildirimleriniz veya katkı önerileriniz için aşağıdaki kanalları kullanabilirsiniz.