---
title: 'Teletype Orbit'
url: 'https://wiki.teletypegames.org/hu/services/teletype-orbit'
markdown: 'https://wiki.teletypegames.org/hu/services/teletype-orbit.md'
lang: hu
date: '2026-08-19'
description: 'A Teletype Orbit olyan játékbolt, mint az itch.io vagy a Steam: Rails 8 + Hotwire alkalmazás a WarpEngine katalógusmotorra építve. A katalógus a WarpEngine-é — szoftverek, kiadások, artifactok, CI-publikálás. Az Orbité mindaz, amire egy boltnak ezen felül szüksége van: ár, rendelés, jogosultság, k…'
taxonomy:
  tag:
    - howto
---

# Teletype Orbit

> A Teletype Orbit olyan játékbolt, mint az itch.io vagy a Steam: Rails 8 + Hotwire alkalmazás a [WarpEngine](https://wiki.teletypegames.org/hu/engines/warp-engine) katalógusmotorra építve. A katalógus a WarpEngine-é — szoftverek, kiadások, artifactok, CI-publikálás. Az Orbité mindaz, amire egy boltnak ezen felül szüksége van: ár, rendelés, jogosultság, kiadó, moderáció, kifizetés.

**Hol tart.** Az Orbit csak helyben fut: a szerveres példányt 2026-09-11-én kivezettük, a forrása a szerveren a `/srv/stacks_disabled` alatt maradt. A kód lépést tart a motorral — 2026-10-26 óta a **WarpEngine 1.5.1**-en van.

# Mit tesz hozzá a WarpEngine-hez

| Terület | Mit hoz az Orbit |
|---|---|
| **Bolt** | katalógusoldalak, keresés, szűrők, termékoldal, kosár, pénztár, rendelések |
| **Könyvtár** | jogosultságok, kapuzott letöltések, kulcsok, ajándékok |
| **Játék** | böngészőben játszható buildek jogosultság-ellenőrzés mögött |
| **Studio** | kiadói portál: termék, ár, áruházi oldal, képek, csatornák, publikálási tokenek, hosztolt buildek |
| **Moderáció** | beküldések, bejelentések, repójóváhagyás |
| **Közösség** | értékelések, fórum, kívánságlista, követés, aktivitás |
| **Pénzügy** | csak hozzáfűzhető főkönyv, bevételmegosztás, kifizetések, számlák |

A motor szavai a motoré maradnak. A `Software` a technikai katalógusbejegyzés, a `Release` egy buildverzió. Az eladható dolog a `Store::Product`, a vevő felé mutató buildmutató pedig a `Studio::Channel`. A kettőt csak egy azonosító köti össze, idegen kulcs nélkül — a motor soft delete-tel dolgozik, így a sorai eltűnhetnek alóla.

# A letöltési kapu

**Korábban.** A WarpEngine `/api/download` és `/file/*` végpontjai nem hitelesítettek, ezért az Orbit mindkettőt lefedte olyan útvonalakkal, amelyek a `mount WarpEngine::Engine` sor elé kerültek. Működött, de az útvonalak sorrendjén múlt — olyan védelem, amely némán elromlik, ha egy sor arrébb kerül.

**Most.** A WarpEngine 0.5.0 óta a motor először megkérdez egy [hozzáférési szabályzatot](https://wiki.teletypegames.org/hu/engines/warp-engine), az Orbité pedig a `Library::AccessPolicy`:

| Metódus | Mit csinál |
|---|---|
| `visible_software_scope` | leszűkíti a `GET /api/software` végpontot a `Store::Product.listed` körre, így a piszkozat, a bírálat alatti, a listáról levett és a privát termékek nem jelennek meg |
| `access_for` | hozzáfűzi az árat, a vásárlási oldalt, és azt, hogy *ez* a hívó birtokolja-e |
| `authorize_download` | lefuttatja azokat a szabályokat, amelyek a `Library::DownloadService` szolgáltatásban már megvoltak: jogosultság, sebességkorlát, engedély, letöltési esemény |

Az `/api/download` már nincs lefedve. A `/file/*` szándékosan még mindig igen: egy webes build **böngészőben** fut, ahol a hitelesítő adat a munkamenet, és a „nem a tiéd" helyes válasza a bejelentkezésre irányítás, nem egy csupasz 403. A motornak egyik sincs meg.

A kockázat nem eltűnt, csak alakot váltott — egy szabályzatot ugyanolyan némán el lehet felejteni bekötni, mint amilyen némán az útvonalsorrend elromlott. A `spec/requests/library/download_gate_spec.rb` a regressziós teszt, és nem opcionális.

# Belépés kliensből

Az Orbit beállítja a WarpEngine eszközhitelesítési folyamatát, így az asztali [WarpEngine Client](https://wiki.teletypegames.org/hu/stores/warp-engine-client) fiókot tud tartani:

```ruby
c.access_token_owner_class  = "Accounts::User"
c.identity_verification_url = "/devices"
c.subject_resolver = ->(request) { request.env["warden"]&.user(:user) }
```

A folyamat a motoré. A két oldal az Orbité, mert a jóváhagyáshoz munkamenet és bejelentkezett ember kell:

| Oldal | Mit csinál |
|---|---|
| `/devices` | valaki beírja a rövid kódot, amit a kliens mutat, látja, melyik eszköz kérdez, majd jóváhagy vagy elutasít |
| `/client_tokens` | az ehhez a fiókhoz bejelentkezett eszközök, és egy eltávolítása |

A `subject_resolver` a másik fele: egy böngésző munkamenetet hordoz, nem bearer tokent, és enélkül a motor visszautasítaná az Orbit saját bejelentkezett látogatóit is.

**A kliens csak azt tudja meg, amire szüksége van, és semmi többet.** Ár, tulajdonlás, hol lehet megvenni, van-e bejelentkezés — mindez a motor általános szerződéséből jön, így a kliens nem hordoz Orbit-specifikus kódot. Egy kliensnek bármelyik WarpEngine-katalógust ki kell tudnia szolgálni; egy belefordított szabály minden másikat elrontana.

# Egy Orbit-oldali hiba, amit érdemes megjegyezni

Minden `WarpEngine::Software` `"development"` státusszal jött létre, és semmi nem mozdította el, mert az Orbitban semmi nem olvassa ezt a mezőt — az oldalai a terméket kérdezik. Egy **katalóguskliens viszont olvassa**: az asztali áruház a kiadott és archivált címeket listázza, a többit kihagyja, így a teljes katalógus láthatatlan volt a számára. A `Store::Product` most `after_save` hívással szinkronban tartja a kettőt (`published → released`, `delisted → archived`, demótermék → `demo`), nem egy szolgáltatás egyik sorában, mert az állapot a moderációs folyamatból és az ActiveAdminból egyaránt változhat.

# A motor frissítése: 0.8-ról 1.5-re

Az ugrás hozta a motor migrációit (a kategória-oszlop, a státusz- és kategóriaszótár, a `shelf_name`), ezeket egy `db:migrate` lefuttatja, és két dolgot, amit a hosztnak magának kellett megcsinálnia:

- **`.kept` mindenhol.** A motormodelleknek a 0.10 óta nincs `default_scope`-juk, így egy `Software`-, `Release`-, `ReleaseAsset`-, `ApplicationToken`-, `Pipeline`-, `PlatformLink`- vagy `Download`-lekérdezés a soft delete-tel törölt sorokat is látja. Az Orbit nagyjából húsz helyen épített a régi scope-ra — egy visszavont eszköztoken ott maradt az eszközök oldalán —, és most mind `.kept`-et kér. Az adatvédelmi törlés szándékos kivétel: a törölt assetek letöltési sorait is anonimizálja.
- **A CI-platformok a hoszt értékeit hordozzák.** A c64-recept a 0.11 óta `exporter` image-ben (`commodore-player`) csomagolja a lejátszóit, és az 1.5 óta a bevy, ebitengine és phaser web-shellje és a LÖVE bundle-előtagja a platformbejegyzésekből jön, azokkal az értékekkel, amelyeket a motor korábban beégetve adott.

# Futtatás

Minden Compose-ban van, az alkalmazás és a Sidekiq-worker is:

```sh
cp .env.example .env
make up
docker compose exec app bin/rails db:seed
```

| Felület | URL |
|---|---|
| Bolt | http://localhost:9140 |
| Admin | http://localhost:9140/admin |
| Levél (Mailpit) | http://localhost:8025 |
| MinIO-konzol | http://localhost:9001 |

Minden publikált port áthelyezhető a `.env`-ben (`ORBIT_WEB_PORT` és a többi), az infrastruktúra pedig csak a `127.0.0.1`-en hallgat.

- **A MinIO a Chainguardtól jön** (`cgr.dev/chainguard/minio`): a MinIO 2025-ben abbahagyta az image-ek kiadását, a `minio/minio` eltűnt a Docker Hubról. Ugyanaz a szerver forrásból építve, csak `:latest` taggel, uid 65532-ként fut — egy régi, root tulajdonú volume-hoz `docker compose down -v` vagy `chown` kell. A `minio-init` egyetlen `mc mb -p`-vel hozza létre a két privát bucketet, és addig próbálkozik, amíg a szerver nem válaszol.
- **A `css` szolgáltatás figyelve marad.** A Tailwind 4 figyelője kilép, amikor a stdin bezárul, és egy TTY nélküli konténer ezt rögtön megteszi; a `bin/dev-css` mindkét bundle figyelőjét `[always]`-szel indítja. A futás közben létrehozott mappát a `docker compose restart css` után veszi észre.

A seedelésnek két szintje van:

- `make seed-core` — referenciaadatok, amelyek élesben is lefutnak: műfajok, címkék, EU-s áfakulcsok, bevételmegosztások, fórumok.
- `make seed-examples` — csak fejlesztéshez való minták. A **valódi** úton mennek végig (Studio → beküldés → jóváhagyás → kosár → fizetési webhook), így a főkönyvben és a riportokban értelmes adat lesz.

# Konvenciók

Az alkalmazás a *Growing Rails Applications in Practice* könyvet követi. A munka nagy részét két szabály végzi:

- **A kontroller triviális, és csak szabványos akciói vannak.** Egy eszköz jóváhagyása `DeviceApprovalsController#create`, nem `DevicesController#approve`. Egy letöltés olyan erőforrás, amelynek a létrehozása kiadja az engedélyt.
- **A logika szolgáltatásokban él**, használati esetenként egy publikus metódussal, és a tesztek súlypontja is ott van: minden ág, minden hibaút.

A teljes terv és a döntések indoklása a repó `NOTES_TELETYPE_ORBIT.md` fájljában van.

'; var prevLevel = 2; for (var i = 0; i < headings.length; i++) { var h = headings\[i\]; var text = h.textContent.trim(); var slug = text.toLowerCase() .replace(/\[áàâä\]/g,'a').replace(/\[éèêë\]/g,'e').replace(/\[íìîï\]/g,'i') .replace(/\[óòôöő\]/g,'o').replace(/\[úùûüű\]/g,'u') .replace(/\[^a-z0-9\]+/g, '-').replace(/^-|-$/g, ''); if (!slug) slug = 'heading-' + i; if (used\[slug\]) { slug += '-' + i; } used\[slug\] = true; h.id = slug; var level = parseInt(h.tagName.charAt(1)); var cls = level > 2 ? ' class="toc-child"' : ''; html += '- [' + text + '](#'%20+%20slug%20+%20')
'; } html += '
'; toc.innerHTML = html; // Scroll-spy: highlight current heading var links = toc.querySelectorAll('a'); var ids = \[\]; for (var j = 0; j < links.length; j++) ids.push(links\[j\].getAttribute('href').slice(1)); function updateActive() { var current = ''; for (var k = 0; k < ids.length; k++) { var el = document.getElementById(ids\[k\]); if (el && el.getBoundingClientRect().top <= 80) current = ids\[k\]; } for (var m = 0; m < links.length; m++) { links\[m\].parentNode.classList.toggle('active', links\[m\].getAttribute('href') === '#' + current); } } window.addEventListener('scroll', updateActive, { passive: true }); updateActive(); })();

---

## Navigation

- Parent: [Szolgáltatások](https://wiki.teletypegames.org/hu/services.md)
- Previous: [Teletype BBS](https://wiki.teletypegames.org/hu/services/teletype-bbs.md)
- Next: [TTG Blog BBS](https://wiki.teletypegames.org/hu/services/ttg-blog-bbs.md)
