Add OIDC sign-in, group-derived roles and declarative instance configuration
Workspaces, group mappings and sign-in methods now come from a configuration file synchronized at startup; workspaces dropped from it are disabled, never deleted. Instance administrators (a new role) see and help every workspace and may delete disabled ones; workspace administrators and employees are derived from the user's groups at every SSO sign-in or administrator edit, and the employee permission set belongs to the workspace. Self-registration is gone: users come from SSO (only when their groups map) or from the administrator. Break-glass bootstrap accounts get an HMAC-derived hourly password that all replicas agree on. First SSO sign-in links a matching email contact to the user. The demo runs on the same model with a generated per-start password. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
e37d583179
commit
4764f3545f
68 files changed
+7220
-964
No files matched your search
@@ -1,2 +1,2 @@
|
||||
const assert=require('node:assert/strict');
|
||||
(async()=>{const browser=await require('./support/browser.cjs').launchBrowser();try{const page=await browser.newPage({viewport:{width:1200,height:850}}),errors=[];page.on('pageerror',e=>errors.push(e.message));await page.goto('http://127.0.0.1:3000/?view=configuration');await page.getByLabel('Username',{exact:true}).fill('alice');await page.getByLabel('Password',{exact:true}).fill('meguri-demo-only');await page.getByRole('button',{name:'Sign in',exact:true}).click();await page.getByRole('button',{name:'Edit rule Project owners during working hours',exact:true}).click();for(const width of [1200,390]){await page.setViewportSize({width,height:850});const button=page.locator('.binding-tweak').last();await button.scrollIntoViewIfNeeded();await button.click();const saved=await page.evaluate(()=>Alpine.$data(document.body).editorScroll);assert(saved>0);const popup=page.locator('.binding-popover');await popup.waitFor();const bounds=await popup.boundingBox();assert(bounds.x>=0&&bounds.x+bounds.width<=width&&bounds.y>=0&&bounds.y+bounds.height<=850);assert(await page.locator('.rule-constructor').isVisible());await popup.screenshot({path:'test-results/binding-popover-'+width+'.png'});await page.getByRole('button',{name:'Done',exact:true}).click();await page.waitForFunction(top=>Math.abs(document.querySelector('[role=dialog]').scrollTop-top)<2,saved);assert.equal(await page.locator('select.template-token,input.template-token,button.template-token').count(),0);assert(await page.locator('.template-token').count()>0);}await page.getByLabel('Iteration collection',{exact:true}).scrollIntoViewIfNeeded();await page.screenshot({path:'test-results/standard-template-controls.png'});assert.deepEqual(errors,[]);console.log('PASS standard controls; template notation retained; modal scroll restored desktop/mobile');}finally{await browser.close();}})().catch(e=>{console.error(e);process.exitCode=1;});
|
||||
(async()=>{const browser=await require('./support/browser.cjs').launchBrowser();try{const page=await browser.newPage({viewport:{width:1200,height:850}}),errors=[];page.on('pageerror',e=>errors.push(e.message));await page.goto('http://127.0.0.1:3000/?view=configuration');await page.getByLabel('Username',{exact:true}).fill('alice');await page.getByLabel('Password',{exact:true}).fill(await require('./support/browser.cjs').demoPassword());await page.getByRole('button',{name:'Sign in',exact:true}).click();await page.getByRole('button',{name:'Edit rule Project owners during working hours',exact:true}).click();for(const width of [1200,390]){await page.setViewportSize({width,height:850});const button=page.locator('.binding-tweak').last();await button.scrollIntoViewIfNeeded();await button.click();const saved=await page.evaluate(()=>Alpine.$data(document.body).editorScroll);assert(saved>0);const popup=page.locator('.binding-popover');await popup.waitFor();const bounds=await popup.boundingBox();assert(bounds.x>=0&&bounds.x+bounds.width<=width&&bounds.y>=0&&bounds.y+bounds.height<=850);assert(await page.locator('.rule-constructor').isVisible());await popup.screenshot({path:'test-results/binding-popover-'+width+'.png'});await page.getByRole('button',{name:'Done',exact:true}).click();await page.waitForFunction(top=>Math.abs(document.querySelector('[role=dialog]').scrollTop-top)<2,saved);assert.equal(await page.locator('select.template-token,input.template-token,button.template-token').count(),0);assert(await page.locator('.template-token').count()>0);}await page.getByLabel('Iteration collection',{exact:true}).scrollIntoViewIfNeeded();await page.screenshot({path:'test-results/standard-template-controls.png'});assert.deepEqual(errors,[]);console.log('PASS standard controls; template notation retained; modal scroll restored desktop/mobile');}finally{await browser.close();}})().catch(e=>{console.error(e);process.exitCode=1;});
|
||||
Reference in new issue
Block a user