Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ playwright-report/

# Local Claude Code tooling/session state
.claude/

# Installed AI skills (skills.sh)
.agents/
skills-lock.json
2 changes: 1 addition & 1 deletion packages/compliance/objectstack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default defineStack({
description: 'Starter template — compliance posture & evidence management on ObjectStack.',
},

requires: ['automation', 'analytics', 'auth', 'ui', 'sharing'],
requires: ['automation', 'triggers', 'analytics', 'auth', 'ui', 'sharing'],

objects: Object.values(objects),
views: Object.values(views),
Expand Down
8 changes: 4 additions & 4 deletions packages/compliance/src/flows/evidence_auto_expire.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export const EvidenceAutoExpireFlow: Flow = {
label: 'Start',
config: {
objectName: 'compliance_evidence',
criteria: 'status == "approved" && expires_on != null && expires_on == daysAgo(0)',
criteriaDialect: 'cel',
triggerType: 'record-after-update',
condition: 'status == "approved" && expires_on != null && expires_on == daysAgo(0)',
},
},
{
Expand All @@ -32,8 +32,8 @@ export const EvidenceAutoExpireFlow: Flow = {
label: 'Mark Expired',
config: {
objectName: 'compliance_evidence',
recordId: '{evidenceId}',
values: { status: 'expired' },
filter: { id: '{record.id}' },
fields: { status: 'expired' },
},
},
{ id: 'end', type: 'end', label: 'End' },
Expand Down
6 changes: 3 additions & 3 deletions packages/compliance/src/flows/evidence_expiring.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export const EvidenceExpiringFlow: Flow = {
label: 'Start',
config: {
objectName: 'compliance_evidence',
criteria:
triggerType: 'record-after-update',
condition:
'status == "approved" && expires_on != null && (expires_on == daysFromNow(30) || expires_on == daysFromNow(7))',
criteriaDialect: 'cel',
},
},
{
Expand All @@ -34,7 +34,7 @@ export const EvidenceExpiringFlow: Flow = {
label: 'Load Evidence',
config: {
objectName: 'compliance_evidence',
filter: { id: '{evidenceId}' },
filter: { id: '{record.id}' },
outputVariable: 'ev',
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const FailedControlEscalationFlow: Flow = {
label: 'Start',
config: {
objectName: 'compliance_assessment',
criteria: 'status == "failed"',
criteriaDialect: 'cel',
triggerType: 'record-after-update',
condition: 'status == "failed"',
},
},
{
Expand All @@ -34,7 +34,7 @@ export const FailedControlEscalationFlow: Flow = {
label: 'Load Assessment',
config: {
objectName: 'compliance_assessment',
filter: { id: '{assessmentId}' },
filter: { id: '{record.id}' },
outputVariable: 'asmt',
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/content/objectstack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default defineStack({

// Opt-in capabilities. Foundational services (queue/job/cache/settings/
// email/storage) are auto-injected by the CLI; we only list the extras.
requires: ['automation', 'analytics', 'auth', 'ui', 'sharing'],
requires: ['automation', 'triggers', 'analytics', 'auth', 'ui', 'sharing'],

objects: Object.values(objects),
views: Object.values(views),
Expand Down
7 changes: 4 additions & 3 deletions packages/content/src/flows/cta_creation_default.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export const CtaCreationDefaultFlow: Flow = {
label: 'Start',
config: {
objectName: 'content_piece',
criteria: 'target_channels != NULL AND ISNEW()',
triggerType: 'record-after-create',
condition: '!isBlank(record.target_channels)',
},
},
{
Expand All @@ -36,7 +37,7 @@ export const CtaCreationDefaultFlow: Flow = {
label: 'Load Piece',
config: {
objectName: 'content_piece',
filter: { id: '{pieceId}' },
filter: { id: '{record.id}' },
outputVariable: 'piece',
},
},
Expand All @@ -56,7 +57,7 @@ export const CtaCreationDefaultFlow: Flow = {
label: 'Create Default CTA',
config: {
objectName: 'content_cta',
values: {
fields: {
piece: '{piece.id}',
label_text: 'Get started',
goal: '{channel.default_cta_goal}',
Expand Down
15 changes: 8 additions & 7 deletions packages/content/src/flows/publication_rollup.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ export const PublicationRollupFlow: Flow = {
label: 'Start',
config: {
objectName: 'content_metric',
criteria:
'ISCHANGED(views) OR ISCHANGED(clicks) OR ISCHANGED(signups) OR ISCHANGED(revenue) OR ISNEW()',
triggerType: 'record-after-update',
condition:
'previous.views != record.views || previous.clicks != record.clicks || previous.signups != record.signups || previous.revenue != record.revenue',
},
},
{
Expand All @@ -44,7 +45,7 @@ export const PublicationRollupFlow: Flow = {
label: 'Load Metric',
config: {
objectName: 'content_metric',
filter: { id: '{metricId}' },
filter: { id: '{record.id}' },
outputVariable: 'metric',
},
},
Expand All @@ -71,8 +72,8 @@ export const PublicationRollupFlow: Flow = {
label: 'Update Publication Rollups',
config: {
objectName: 'content_publication',
recordId: '{metric.publication}',
values: {
filter: { id: '{metric.publication}' },
fields: {
total_views: '{pubTotals.views_sum}',
total_clicks: '{pubTotals.clicks_sum}',
total_signups: '{pubTotals.signups_sum}',
Expand Down Expand Up @@ -113,8 +114,8 @@ export const PublicationRollupFlow: Flow = {
label: 'Update Piece Rollups',
config: {
objectName: 'content_piece',
recordId: '{publication.piece}',
values: {
filter: { id: '{publication.piece}' },
fields: {
total_views: '{pieceTotals.views_sum}',
total_clicks: '{pieceTotals.clicks_sum}',
total_signups: '{pieceTotals.signups_sum}',
Expand Down
12 changes: 6 additions & 6 deletions packages/content/src/flows/publish_approval.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export const PublishApprovalFlow: Flow = {
label: 'Start',
config: {
objectName: 'content_piece',
criteria: 'status == "in_review"',
criteriaDialect: 'cel',
triggerType: 'record-after-update',
condition: 'status == "in_review"',
},
},
{
Expand All @@ -58,8 +58,8 @@ export const PublishApprovalFlow: Flow = {
label: 'Mark Approved',
config: {
objectName: 'content_piece',
recordId: '{pieceId}',
values: { status: 'approved' },
filter: { id: '{record.id}' },
fields: { status: 'approved' },
},
},
{
Expand All @@ -79,8 +79,8 @@ export const PublishApprovalFlow: Flow = {
label: 'Send Back to Drafting',
config: {
objectName: 'content_piece',
recordId: '{pieceId}',
values: { status: 'drafting' },
filter: { id: '{record.id}' },
fields: { status: 'drafting' },
},
},
{
Expand Down
11 changes: 6 additions & 5 deletions packages/content/src/flows/signal_to_topic_promotion.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export const SignalToTopicPromotionFlow: Flow = {
label: 'Start',
config: {
objectName: 'content_signal',
criteria: 'status == "promoted" && PRIOR(status) != "promoted"',
triggerType: 'record-after-update',
condition: 'status == "promoted" && PRIOR(status) != "promoted"',
},
},
{
Expand All @@ -36,7 +37,7 @@ export const SignalToTopicPromotionFlow: Flow = {
label: 'Load Signal',
config: {
objectName: 'content_signal',
filter: { id: '{signalId}' },
filter: { id: '{record.id}' },
outputVariable: 'signal',
},
},
Expand All @@ -46,7 +47,7 @@ export const SignalToTopicPromotionFlow: Flow = {
label: 'Create Topic',
config: {
objectName: 'content_topic',
values: {
fields: {
title: '{signal.recommended_topic_title}',
brief:
'Promoted from signal "{signal.headline}". Source: {signal.source_url}.\n\n{signal.summary}',
Expand All @@ -65,8 +66,8 @@ export const SignalToTopicPromotionFlow: Flow = {
label: 'Link Topic Back to Signal',
config: {
objectName: 'content_signal',
recordId: '{signal.id}',
values: { promoted_topic: '{topic.id}' },
filter: { id: '{record.id}' },
fields: { promoted_topic: '{topic.id}' },
},
},
{
Expand Down
5 changes: 3 additions & 2 deletions packages/content/src/flows/stamp_lifecycle_timestamps.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const StampLifecycleTimestampsFlow: Flow = {
label: 'Start',
config: {
objectName: 'content_piece',
criteria: 'ISCHANGED(status)',
triggerType: 'record-after-update',
condition: 'ISCHANGED(status)',
},
},
{
Expand All @@ -37,7 +38,7 @@ export const StampLifecycleTimestampsFlow: Flow = {
label: 'Load Piece',
config: {
objectName: 'content_piece',
filter: { id: '{pieceId}' },
filter: { id: '{record.id}' },
outputVariable: 'piece',
},
},
Expand Down
5 changes: 2 additions & 3 deletions packages/contracts/objectstack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ export default defineStack({
version: '0.1.0',
type: 'app',
name: 'Contracts',
description:
'Starter template — post-signature contract lifecycle management on ObjectStack.',
description: 'Starter template — post-signature contract lifecycle management on ObjectStack.',
},

// Opt-in capabilities. Foundational services (queue/job/cache/settings/
// email/storage) are auto-injected by the CLI; we only list the extras.
requires: ['automation', 'analytics', 'auth', 'ui', 'sharing'],
requires: ['automation', 'triggers', 'analytics', 'auth', 'ui', 'sharing'],

objects: Object.values(objects),
views: Object.values(views),
Expand Down
5 changes: 3 additions & 2 deletions packages/contracts/src/flows/obligation_overdue.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export const ObligationOverdueFlow: Flow = {
label: 'Start',
config: {
objectName: 'contracts_obligation',
criteria: 'due_date < TODAY() AND status = "open"',
triggerType: 'record-after-update',
condition: 'due_date != null && due_date < daysFromNow(0) && status == "open"',
},
},
{
Expand All @@ -32,7 +33,7 @@ export const ObligationOverdueFlow: Flow = {
label: 'Get Obligation',
config: {
objectName: 'contracts_obligation',
filter: { id: '{obligationId}' },
filter: { id: '{record.id}' },
outputVariable: 'obligationRecord',
},
},
Expand Down
6 changes: 3 additions & 3 deletions packages/contracts/src/flows/renewal_alert.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export const ContractRenewalAlertFlow: Flow = {
label: 'Start',
config: {
objectName: 'contracts_contract',
criteria:
triggerType: 'record-after-update',
condition:
'status == "active" && end_date != null && (end_date == daysFromNow(60) || end_date == daysFromNow(30) || end_date == daysFromNow(7))',
criteriaDialect: 'cel',
},
},
{
Expand All @@ -42,7 +42,7 @@ export const ContractRenewalAlertFlow: Flow = {
label: 'Get Contract',
config: {
objectName: 'contracts_contract',
filter: { id: '{contractId}' },
filter: { id: '{record.id}' },
outputVariable: 'contractRecord',
},
},
Expand Down
8 changes: 4 additions & 4 deletions packages/contracts/src/flows/renewal_draft.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ export const ContractRenewalDraftFlow: Flow = {
label: 'Start',
config: {
objectName: 'contracts_contract',
criteria:
triggerType: 'record-after-update',
condition:
'status == "active" && auto_renew == false && end_date != null && renewal_notice_days != null && end_date == daysFromNow(renewal_notice_days)',
criteriaDialect: 'cel',
},
},
{
Expand All @@ -45,7 +45,7 @@ export const ContractRenewalDraftFlow: Flow = {
label: 'Load Parent Contract',
config: {
objectName: 'contracts_contract',
filter: { id: '{contractId}' },
filter: { id: '{record.id}' },
outputVariable: 'parent',
},
},
Expand All @@ -55,7 +55,7 @@ export const ContractRenewalDraftFlow: Flow = {
label: 'Create Renewal Draft',
config: {
objectName: 'contracts_contract',
values: {
fields: {
title: 'Renewal — {parent.title}',
party: '{parent.party}',
contract_type: '{parent.contract_type}',
Expand Down
5 changes: 2 additions & 3 deletions packages/expense/objectstack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ export default defineStack({
version: '0.1.0',
type: 'app',
name: 'Expense',
description:
'Starter template — employee expense & reimbursement management on ObjectStack.',
description: 'Starter template — employee expense & reimbursement management on ObjectStack.',
},

requires: ['automation', 'analytics', 'auth', 'ui', 'sharing'],
requires: ['automation', 'triggers', 'analytics', 'auth', 'ui', 'sharing'],

objects: Object.values(objects),
views: Object.values(views),
Expand Down
12 changes: 6 additions & 6 deletions packages/expense/src/flows/expense_approval.flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export const ExpenseApprovalFlow: Flow = {
label: 'Start',
config: {
objectName: 'expense_report',
criteria: 'status == "submitted"',
criteriaDialect: 'cel',
triggerType: 'record-after-update',
condition: 'status == "submitted"',
},
},
{
Expand All @@ -58,8 +58,8 @@ export const ExpenseApprovalFlow: Flow = {
label: 'Mark Approved',
config: {
objectName: 'expense_report',
recordId: '{reportId}',
values: { status: 'approved' },
filter: { id: '{record.id}' },
fields: { status: 'approved' },
},
},
{
Expand All @@ -79,8 +79,8 @@ export const ExpenseApprovalFlow: Flow = {
label: 'Mark Rejected',
config: {
objectName: 'expense_report',
recordId: '{reportId}',
values: { status: 'rejected' },
filter: { id: '{record.id}' },
fields: { status: 'rejected' },
},
},
{
Expand Down
Loading
Loading