This commit is contained in:
nessar committed 2026-04-05 16:04:37 +02:00
1 parent e8b1ac5ba2
commit 7a6ef2f2ab
5 files changed
+348

No files matched your search

@@ -0,0 +1,52 @@
name: Deploy Privacy Policy Image
on:
push:
branches:
- main
permissions:
contents: read
packages: write
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set image name
id: vars
run: echo "image_name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.vars.outputs.image_name }}
tags: |
type=raw,value=latest
type=sha,format=long,prefix=sha-
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
+10
View File
@@ -0,0 +1,10 @@
FROM nginx:1.29-alpine
RUN rm -f /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY privacy-policy/ /usr/share/nginx/html/privacy-policy/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+37
View File
@@ -0,0 +1,37 @@
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
index index.html;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
location = / {
return 301 /privacy-policy/;
}
location /privacy-policy/ {
try_files $uri $uri/ /privacy-policy/index.html;
}
location ~* \.(?:css|js|mjs|json|txt|xml|svg|ico|png|jpg|jpeg|webp)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";
try_files $uri =404;
}
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache";
try_files $uri =404;
}
location / {
try_files $uri =404;
}
}
+147
View File
@@ -0,0 +1,147 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>21 (Le 21) Privacy Policy</title>
<meta
name="description"
content="Privacy Policy for 21 (Le 21), a local multiplayer dice game."
/>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main class="container">
<header class="hero">
<p class="eyebrow">Privacy Policy</p>
<h1>21 (Le 21)</h1>
<p class="subtitle">
This Privacy Policy explains how 21 (Le 21) handles information when you use the app.
</p>
<p class="meta"><strong>Last updated:</strong> April 5, 2026</p>
</header>
<section>
<h2>Overview</h2>
<p>
21 (Le 21) is a local multiplayer dice game. The app is designed to work without account
creation and without collecting personal identity information for remote profiling.
</p>
</section>
<section>
<h2>Information We Process</h2>
<ul>
<li>
<strong>Game data you enter:</strong> player names, optional magic-number settings,
match history, and leaderboard values.
</li>
<li>
<strong>Gameplay telemetry for in-app features:</strong> dice outcomes and round
statistics used to calculate scores and display game events.
</li>
<li>
<strong>Technical interaction signals:</strong> shake/rub gestures used only to trigger
dice rolls during gameplay.
</li>
</ul>
</section>
<section>
<h2>How Data Is Used</h2>
<ul>
<li>To run core gameplay logic, scoring, and tie-break mechanics.</li>
<li>To save your game preferences and profile options on your device.</li>
<li>To restore local leaderboard and configuration between app sessions.</li>
</ul>
</section>
<section>
<h2>Data Storage</h2>
<p>
App state is persisted locally on your device using Expo FileSystem storage. This may
include game settings, saved profiles, and leaderboard values. This local data is
not intended for sale and is not used for advertising.
</p>
</section>
<section>
<h2>Permissions</h2>
<ul>
<li><strong>Internet:</strong> used to load external 3D dice rendering assets.</li>
<li>
<strong>Accelerometer/Sensors:</strong> used for optional shake-to-roll gameplay input.
</li>
<li><strong>Vibration:</strong> may be used to enhance gameplay feedback.</li>
<li>
<strong>Storage access (platform-dependent):</strong> used by runtime components for local
file operations and compatibility.
</li>
</ul>
</section>
<section>
<h2>Third-Party Services and Libraries</h2>
<ul>
<li>
<strong>UNPKG CDN and @3d-dice/dice-box:</strong> used to fetch 3D dice engine scripts and
assets for rendering dice in an in-app WebView.
</li>
<li>
<strong>Expo and React Native ecosystem libraries:</strong> used for app runtime, UI,
navigation, and local device APIs.
</li>
</ul>
<p>
No Firebase SDK, analytics SDK, ad SDK, or user authentication SDK was detected in the
current app codebase.
</p>
</section>
<section>
<h2>Data Sharing</h2>
<p>
The app does not intentionally share your personal data with third parties for marketing.
Data may still be processed by infrastructure involved in delivering third-party assets
(e.g., content delivery networks) when those assets are requested by the app.
</p>
</section>
<section>
<h2>Your Choices</h2>
<ul>
<li>You can choose whether to enable gameplay features like shake or rub controls.</li>
<li>You can clear app data through your device settings to remove locally stored data.</li>
</ul>
</section>
<section>
<h2>Children's Privacy</h2>
<p>
21 (Le 21) does not knowingly collect personal information from children through
account-based features.
</p>
</section>
<section>
<h2>Policy Updates</h2>
<p>
This Privacy Policy may be updated from time to time. Changes will be reflected on this
page with an updated "Last updated" date.
</p>
</section>
<section>
<h2>Contact</h2>
<p>
For privacy questions, contact the project maintainer through the repository issue tracker:
</p>
<p>
<a href="https://github.com/THoguet/21/issues" rel="noopener noreferrer"
>https://github.com/THoguet/21/issues</a
>
</p>
</section>
</main>
</body>
</html>
+102
View File
@@ -0,0 +1,102 @@
:root {
color-scheme: light;
--bg: #f5f7fb;
--surface: #ffffff;
--text: #1d2430;
--muted: #5b667a;
--accent: #1a73e8;
--border: #dce3ef;
--shadow: 0 8px 30px rgba(20, 37, 63, 0.08);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
sans-serif;
background: linear-gradient(180deg, #eef3fb 0%, var(--bg) 60%);
color: var(--text);
line-height: 1.6;
}
.container {
width: min(920px, calc(100% - 2rem));
margin: 2rem auto;
padding: 1.5rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
box-shadow: var(--shadow);
}
.hero {
padding-bottom: 1rem;
border-bottom: 1px solid var(--border);
margin-bottom: 1.5rem;
}
.eyebrow {
margin: 0;
color: var(--accent);
font-weight: 700;
letter-spacing: 0.02em;
text-transform: uppercase;
font-size: 0.85rem;
}
h1 {
margin: 0.2rem 0 0.4rem;
font-size: clamp(1.7rem, 4vw, 2.4rem);
line-height: 1.2;
}
.subtitle,
.meta {
margin: 0.25rem 0;
color: var(--muted);
}
section {
margin: 1.2rem 0;
}
h2 {
margin: 0 0 0.5rem;
font-size: 1.1rem;
line-height: 1.3;
}
p,
ul {
margin: 0;
}
ul {
padding-left: 1.2rem;
}
li + li {
margin-top: 0.45rem;
}
a {
color: var(--accent);
word-break: break-word;
}
a:hover,
a:focus-visible {
text-decoration-thickness: 2px;
}
@media (max-width: 640px) {
.container {
width: calc(100% - 1rem);
margin: 0.75rem auto;
padding: 1rem;
border-radius: 12px;
}
}