Snapshot: full project state

This commit is contained in:
2026-10-06 23:43:48 -07:00
commit 4f56907c45
20 changed files with 1207 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
{% extends "base.html" %}
{% block content %}
<div class="app-head">
<div>
<h1>{{ a['institution'] }}</h1>
<div class="muted">{{ a['account_type'] | replace('_', ' ') | title }} · started {{ a['created_at'] }}</div>
</div>
<form method="post" action="{{ url_for('set_status', app_id=a['id']) }}" class="inline">
<select name="status" onchange="this.form.submit()">
{% for s in ['researching', 'in_progress', 'submitted', 'approved', 'denied'] %}
<option value="{{ s }}" {% if a['status'] == s %}selected{% endif %}>{{ s }}</option>
{% endfor %}
</select>
</form>
</div>
<h2>Requirements</h2>
<ul class="checklist">
{% for item in items %}
<li>
<form method="post" action="{{ url_for('toggle_item', app_id=a['id'], item_id=item['id']) }}">
<button type="submit" class="checkbox {{ 'checked' if item['done'] else '' }}">
{{ '✓' if item['done'] else '' }}
</button>
<span class="{{ 'done' if item['done'] else '' }}">{{ item['label'] }}</span>
</form>
</li>
{% endfor %}
</ul>
<h2>Your info (for pre-filling this application)</h2>
{% if profile %}
<div class="profile-panel">
{% for key, label in [('full_name','Name'),('date_of_birth','DOB'),('ssn','SSN/TIN'),('address_line1','Address'),('city','City'),('state','State'),('zip','ZIP'),('phone','Phone'),('email','Email')] %}
{% if profile.get(key) %}
<div><span class="plabel">{{ label }}</span><span class="pvalue">{{ profile[key] }}</span></div>
{% endif %}
{% endfor %}
</div>
<p class="muted">Edit in <a href="{{ url_for('profile') }}">Profile</a>.</p>
{% else %}
<p class="muted">No profile yet. <a href="{{ url_for('profile') }}">Add your info</a> to pre-fill.</p>
{% endif %}
<h2>Notes</h2>
<form method="post" action="{{ url_for('set_notes', app_id=a['id']) }}" class="form">
<textarea name="notes" rows="3">{{ a['notes'] }}</textarea>
<button type="submit" class="btn">Save notes</button>
</form>
<form method="post" action="{{ url_for('delete_application', app_id=a['id']) }}"
onsubmit="return confirm('Delete this application?');">
<button type="submit" class="btn danger">Delete application</button>
</form>
{% endblock %}

41
templates/base.html Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>Castor — Account Onboarding</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header>
<div class="brand">
<span class="logo">✦</span>
<span>Castor</span>
<span class="tag">account onboarding assistant</span>
</div>
<nav>
<a href="{{ url_for('index') }}">Applications</a>
<a href="{{ url_for('new_application') }}">+ New</a>
<a href="{{ url_for('profile') }}">Profile</a>
<a href="{{ url_for('vault') }}">Vault</a>
</nav>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for cat, msg in messages %}
<div class="flash {{ cat }}">{{ msg }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
<footer>
<p>For opening <strong>your own</strong> accounts in <strong>your own name</strong>. No identity fabrication, no bulk signups, no KYC evasion.</p>
</footer>
</body>
</html>

57
templates/index.html Normal file
View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>Castor — Signup Dashboard</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header>
<div class="brand"><span class="logo">✦</span><span>Castor</span><span class="tag">signup dashboard</span></div>
<nav>
<a href="{{ url_for('index') }}">Providers</a>
<a href="{{ url_for('profile_route') }}">Your Info ({{ filled }}/{{ total }})</a>
</nav>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for cat, msg in messages %}<div class="flash {{ cat }}">{{ msg }}</div>{% endfor %}
{% endif %}
{% endwith %}
<div class="hero">
<h1>Open accounts without retyping your info</h1>
<p class="muted">Check the providers you want, hit launch — each signup page opens with your details already filled. You finish the CAPTCHA / verification and submit.</p>
</div>
<form method="post" action="{{ url_for('launch') }}">
{% for cat in categories %}
<h2 class="cat">{{ cat | replace('_', ' ') | title }}</h2>
<div class="cards">
{% for p in providers if p['category'] == cat %}
<label class="provider">
<input type="checkbox" name="providers" value="{{ p['id'] }}">
<span class="pname">{{ p['name'] }}</span>
<span class="pnote">{{ p['note'] }}</span>
<a class="plink" href="{{ p['url'] }}" target="_blank" rel="noopener" onclick="event.stopPropagation()">open ↗</a>
</label>
{% endfor %}
</div>
{% endfor %}
<div class="launchbar">
<button type="submit" class="btn primary big">Launch &amp; autofill selected</button>
<span class="muted">opens each in a new browser tab with your info filled</span>
</div>
</form>
</main>
<footer>
<p>Fills <strong>your own</strong> info into forms <strong>you</strong> submit. No identity fabrication, no bulk signups, no KYC evasion.</p>
</footer>
</body>
</html>

36
templates/new.html Normal file
View File

@@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block content %}
<h1>New Application</h1>
<p class="muted">Pick the account type. Castor loads the real KYC requirements that institutions ask for.</p>
<form method="post" class="form">
<label>Account type
<select name="account_type" id="account_type">
{% for key, info in reqs.items() %}
<option value="{{ key }}">{{ info['label'] }}</option>
{% endfor %}
</select>
</label>
<div id="preview" class="preview"></div>
<label>Institution
<input type="text" name="institution" placeholder="e.g. Chase, Vanguard, Coinbase, PayPal" required>
</label>
<button type="submit" class="btn primary">Start application</button>
</form>
<script>
const reqs = {{ reqs | tojson }};
const sel = document.getElementById('account_type');
const preview = document.getElementById('preview');
function render() {
const info = reqs[sel.value];
preview.innerHTML = '<strong>Requirements:</strong><ul>' +
info.requirements.map(r => '<li>' + r + '</li>').join('') + '</ul>';
}
sel.addEventListener('change', render);
render();
</script>
{% endblock %}

42
templates/profile.html Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>Castor — Your Info</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header>
<div class="brand"><span class="logo">✦</span><span>Castor</span><span class="tag">signup dashboard</span></div>
<nav>
<a href="{{ url_for('index') }}">Providers</a>
<a href="{{ url_for('profile_route') }}">Your Info</a>
</nav>
</header>
<main>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for cat, msg in messages %}<div class="flash {{ cat }}">{{ msg }}</div>{% endfor %}
{% endif %}
{% endwith %}
<h1>Your Info</h1>
<p class="muted">Stored locally, used only to auto-fill <strong>your own</strong> signup forms.</p>
<form method="post" class="form">
{% for key, label in fields %}
<label>{{ label }}
<input type="text" name="{{ key }}" value="{{ profile.get(key, '') }}" autocomplete="off">
</label>
{% endfor %}
<button type="submit" class="btn primary">Save</button>
</form>
</main>
<footer>
<p>Fills <strong>your own</strong> info into forms <strong>you</strong> submit. No identity fabrication, no bulk signups, no KYC evasion.</p>
</footer>
</body>
</html>

37
templates/vault.html Normal file
View File

@@ -0,0 +1,37 @@
{% extends "base.html" %}
{% block content %}
<h1>Vault</h1>
<p class="muted">Your identity documents, encrypted at rest with a key generated on this machine.</p>
<form method="post" action="{{ url_for('vault_upload') }}" enctype="multipart/form-data" class="form">
<label>Upload document (20 MB max)
<input type="file" name="file" required>
</label>
<button type="submit" class="btn primary">Encrypt &amp; store</button>
</form>
{% if docs %}
<table class="table">
<thead><tr><th>File</th><th>Type</th><th>SHA-256</th><th>Uploaded</th><th></th></tr></thead>
<tbody>
{% for d in docs %}
<tr>
<td>{{ d['filename'] }}</td>
<td>{{ d['mime'] }}</td>
<td class="mono">{{ d['sha256'][:16] }}…</td>
<td>{{ d['uploaded_at'] }}</td>
<td class="row-actions">
<a class="btn small" href="{{ url_for('vault_download', doc_id=d['id']) }}">Download</a>
<form method="post" action="{{ url_for('vault_delete', doc_id=d['id']) }}" class="inline"
onsubmit="return confirm('Delete this document?');">
<button type="submit" class="btn small danger">Delete</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="muted">No documents stored yet.</p>
{% endif %}
{% endblock %}