my-provider-dash-manager 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -10
- package/package.json +1 -1
- package/src/main.js +13 -4
package/README.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# My Provider Dash Manager
|
|
2
2
|
|
|
3
|
-
**One desktop app for every
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
of pages.
|
|
3
|
+
**One desktop app for every account you own.** Keep several Google, Microsoft, AWS, Vercel,
|
|
4
|
+
Netlify, Cloudflare, Supabase, GitHub, npm, Stripe, Gmail, Outlook, Proton Mail (and 25 more) accounts
|
|
5
|
+
signed in at the same time, each in a fully isolated session, and switch between them instantly — the
|
|
6
|
+
way a browser handles tabs, but built around *accounts* instead of pages.
|
|
8
7
|
|
|
9
8
|
<sub>Windows desktop app · Electron 43 · local-first · no telemetry, no account, no server ·
|
|
10
9
|
source-available licence: free for personal and commercial use</sub>
|
|
@@ -141,11 +140,26 @@ sessions, one place.
|
|
|
141
140
|
account's login, and a saved password is never filled into a page outside the service's domains.
|
|
142
141
|
|
|
143
142
|
### Built-in services
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
Thirty-seven services ship ready to use, grouped by category. The rail and Home show only the ones
|
|
144
|
+
you have accounts on; everything else sits one click away behind **Add account**, a searchable picker.
|
|
145
|
+
|
|
146
|
+
| Category | Services |
|
|
147
|
+
|---|---|
|
|
148
|
+
| Hosting & deploy | Vercel, Netlify, Cloudflare, Railway, Render, Fly.io, Heroku, DigitalOcean |
|
|
149
|
+
| Databases | Supabase, Neon |
|
|
150
|
+
| Code & packages | GitHub, GitLab, npm, PyPI, Docker Hub, Hugging Face |
|
|
151
|
+
| Payments | Stripe |
|
|
152
|
+
| Google | Google Account, Gmail, Google Cloud, Firebase, Google Workspace Admin, Google Play Console, Google AI Studio |
|
|
153
|
+
| Microsoft | Microsoft Account, Outlook, Azure, Microsoft 365 Admin |
|
|
154
|
+
| Mail | Proton Mail, Zoho Mail, Fastmail, Yahoo Mail, Tuta Mail, iCloud Mail |
|
|
155
|
+
| Cloud | AWS |
|
|
156
|
+
| AI | OpenAI Platform, Claude Platform (Anthropic) |
|
|
157
|
+
|
|
158
|
+
Every login page is verified to load inside an isolated partition, landing on a host the credential
|
|
159
|
+
guard trusts, by `npm run smoke:services`. Google sign-in works directly in the app (verified against
|
|
160
|
+
Google's own sign-in flow); "Continue with Google" buttons on *other* sites remain blocked by Google
|
|
161
|
+
in embedded browsers, so use email/password or GitHub there. Anything else can be added by URL or as
|
|
162
|
+
a plugin (below).
|
|
149
163
|
|
|
150
164
|
### API status
|
|
151
165
|
Paste a read-only API token into an account and its Home card shows live status — project, app,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-provider-dash-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Manage many accounts per cloud service (Vercel, Netlify, Supabase, Cloudflare, Railway, Render, GitHub) in one desktop app \u2014 isolated persistent sessions, one tab per account.",
|
|
5
5
|
"main": "src/main.js",
|
|
6
6
|
"scripts": {
|
package/src/main.js
CHANGED
|
@@ -58,8 +58,12 @@ function userData(name) { return userDataPath(name); }
|
|
|
58
58
|
// Built-in curated services + user-added generic ones (Phase 2) + plugin manifests (Phase 3).
|
|
59
59
|
let pluginServices = [];
|
|
60
60
|
let pluginErrors = [];
|
|
61
|
+
// Sign-in infrastructure the managed services depend on but that is not a credential host: the
|
|
62
|
+
// ad-blocker must leave these alone (EasyList rules hit e.g. accounts.youtube.com/CheckConnection,
|
|
63
|
+
// which Google sign-in loads in an iframe). This list grants NO password trust — see serviceHosts.
|
|
64
|
+
const AUTH_INFRA_HOSTS = ['accounts.youtube.com', 'accounts.google.com', 'gstatic.com', 'login.microsoftonline.com', 'login.live.com', 'msftauth.net', 'msauth.net', 'appleid.cdn-apple.com'];
|
|
61
65
|
function refreshManagedHosts() {
|
|
62
|
-
const hosts = new Set();
|
|
66
|
+
const hosts = new Set(AUTH_INFRA_HOSTS);
|
|
63
67
|
for (const s of allServices()) for (const h of serviceHosts(s.key)) hosts.add(h);
|
|
64
68
|
content.setManagedHosts([...hosts]);
|
|
65
69
|
}
|
|
@@ -266,8 +270,12 @@ class ViewManager {
|
|
|
266
270
|
});
|
|
267
271
|
const onNav = (_e, url2) => {
|
|
268
272
|
tab.url = url2;
|
|
269
|
-
// conservative sign-in heuristic: sitting on the service's login page means not signed in
|
|
270
|
-
|
|
273
|
+
// conservative sign-in heuristic: sitting on the service's login page means not signed in.
|
|
274
|
+
// When the service authenticates on a separate host (accounts.google.com, login.live.com,
|
|
275
|
+
// id.heroku.com…) any URL on that host counts as "signing in".
|
|
276
|
+
const loginHost = creds.hostOf(service.loginUrl);
|
|
277
|
+
const onAuthHost = loginHost && loginHost !== creds.hostOf(service.dashboardUrl) && creds.hostOf(url2) === loginHost;
|
|
278
|
+
tab.lastState = (url2.startsWith(service.loginUrl) || onAuthHost) ? 'signin' : 'ok';
|
|
271
279
|
const a = findAccount(svc, id);
|
|
272
280
|
if (a) { a.lastState = tab.lastState; store.save(); }
|
|
273
281
|
this.emitState();
|
|
@@ -609,8 +617,9 @@ async function runSmokeServices() {
|
|
|
609
617
|
const check = (name, ok, detail = '') => { results.checks.push({ name, ok, detail }); console.log(`[smoke:services] ${ok ? 'PASS' : 'FAIL'} ${name} ${detail}`); };
|
|
610
618
|
const keys = SERVICES.map(s => s.key);
|
|
611
619
|
check('unique-keys', new Set(keys).size === keys.length, `${keys.length} services`);
|
|
612
|
-
check('definitions-complete', SERVICES.every(s => s.name && /^https:\/\//.test(s.dashboardUrl) && /^https:\/\//.test(s.loginUrl) && /^https:\/\//.test(s.signupUrl) && /^#[0-9a-f]{6}$/i.test(s.color) && ['ok', 'warn', 'one-per-person'].includes(s.multiAccountPolicy)));
|
|
620
|
+
check('definitions-complete', SERVICES.every(s => s.name && /^https:\/\//.test(s.dashboardUrl) && /^https:\/\//.test(s.loginUrl) && /^https:\/\//.test(s.signupUrl) && /^#[0-9a-f]{6}$/i.test(s.color) && ['ok', 'warn', 'one-per-person'].includes(s.multiAccountPolicy) && typeof s.category === 'string' && s.category));
|
|
613
621
|
check('partition-ids-safe', SERVICES.every(s => /^[a-z0-9_-]+$/.test(s.key)), keys.join(','));
|
|
622
|
+
check('extra-hosts-are-specific', SERVICES.every(s => (s.extraHosts || []).every(h => /^[a-z0-9.-]+\.[a-z]+$/.test(h) && h.split('.').length >= 3)));
|
|
614
623
|
check('extra-hosts-in-guard', serviceHosts('dockerhub').includes('login.docker.com') && originAllowed('dockerhub', 'https://login.docker.com/u/login?x=1') && !originAllowed('dockerhub', 'https://evil.example/'));
|
|
615
624
|
|
|
616
625
|
const win = new BaseWindow({ width: 1280, height: 800, show: false });
|