Skip to content

fix: add strict TemplateLogic compile validation#165

Open
Rishabh060105 wants to merge 5 commits into
accordproject:mainfrom
Rishabh060105:Rishabh060105/strict-template-logic-validation
Open

fix: add strict TemplateLogic compile validation#165
Rishabh060105 wants to merge 5 commits into
accordproject:mainfrom
Rishabh060105:Rishabh060105/strict-template-logic-validation

Conversation

@Rishabh060105

Copy link
Copy Markdown

Summary

Fixes #163 by adding opt-in strict validation to TemplateArchiveProcessor.compileLogic().

Today compileLogic() returns emitted code without checking whether it contains a class extending TemplateLogic, so downstream sandbox consumers only discover malformed output later at execution time. This change adds a strict mode for callers that need that guarantee, while keeping the current default behavior unchanged for existing plain-class logic.

Changes

  • add CompileLogicOptions to TemplateArchiveProcessor.compileLogic()
  • keep backward compatibility with the existing boolean cache argument
  • support requireTemplateLogic: true to enforce that logic/logic.ts defines a class extending TemplateLogic
  • validate the source using the TypeScript AST before returning compiled output
  • keep default compilation behavior unchanged so existing plain default-exported classes still compile unless strict mode is enabled
  • export CompileLogicOptions from the package root
  • add regression coverage for:
    • default compile behavior
    • strict compile success when the logic extends TemplateLogic
    • strict compile failure for plain default-exported classes

Test

Implemented and pushed on branch Rishabh060105/strict-template-logic-validation.

Validation notes:

  • npm test -- --runTestsByPath test/TemplateArchiveProcessor.test.ts --runInBand
    • currently blocked by existing upstream build/type issues unrelated to this change
  • verified the new compileLogic() behavior directly with a focused runtime stub check covering:
    • strict mode success for TemplateLogic subclasses
    • default mode success for plain classes
    • strict mode rejection for plain classes
    • cache interaction so strict validation is not bypassed by a previously cached non-strict compile

Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
@Rishabh060105
Rishabh060105 requested a review from a team July 12, 2026 17:11
Comment thread src/TemplateArchiveProcessor.ts Outdated
Comment thread src/TemplateArchiveProcessor.ts Outdated
@23harshitkumar

Copy link
Copy Markdown
Contributor

@Rishabh060105 This is great work. Thanks for the contribution! I left some comments!

Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
@Rishabh060105

Copy link
Copy Markdown
Author

Hi @23harshitkumar have addressed the issues raised above, please go through it. Thanks!

@23harshitkumar

23harshitkumar commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Thanks @Rishabh060105! You have my approval (as the "issue creator").

@sanketshevkar @mttrbrts Could we consider merging it?

@mttrbrts

Copy link
Copy Markdown
Member

Thanks @Rishabh060105! You have my approval (as the "issue creator").

@sanketshevkar @mttrbrts Could we consider merging it?

I'm tempted to say that this is a bug, and that the opt-in flag is unnecessary. Let's discuss on the WG call tomorrow?

@github-actions github-actions Bot added the maintainer-engaged A maintainer has commented or reviewed this item label Jul 15, 2026
@mttrbrts mttrbrts closed this Jul 15, 2026
@mttrbrts mttrbrts reopened this Jul 15, 2026
@mttrbrts

Copy link
Copy Markdown
Member

Thanks @Rishabh060105! You have my approval (as the "issue creator").
@sanketshevkar @mttrbrts Could we consider merging it?

I'm tempted to say that this is a bug, and that the opt-in flag is unnecessary. Let's discuss on the WG call tomorrow?

If these templates will never work without this TemplateLogic extension, then this is a pure bug fix and we don't need the flag to opt-in.

@Rishabh060105

Copy link
Copy Markdown
Author

Thanks @Rishabh060105! You have my approval (as the "issue creator").
@sanketshevkar @mttrbrts Could we consider merging it?

I'm tempted to say that this is a bug, and that the opt-in flag is unnecessary. Let's discuss on the WG call tomorrow?

If these templates will never work without this TemplateLogic extension, then this is a pure bug fix and we don't need the flag to opt-in.

Hi @mttrbrts , I checked this against both template-engine and template-playground.

For the playground/sandbox flow, I agree with the concern: that path expects the compiled output to contain a class extending TemplateLogic, otherwise it cannot safely derive the class constructor.

For template-engine itself though, this is not currently enforced at runtime. JavaScriptEvaluator imports the default export, constructs it, and calls the requested method, without checking extends TemplateLogic. So a plain default-exported class with the expected methods can still work today.

That is why I kept this as an opt-in flag: it lets sandbox consumers enforce the stricter contract without changing existing engine behavior by default. If we agree with the fact that plain logic classes are unsupported by contract, I’m happy to simplify the PR and make the validation unconditional.

Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
@23harshitkumar

Copy link
Copy Markdown
Contributor

If these templates will never work without this TemplateLogic extension, then this is a pure bug fix and we don't need the flag to opt-in.

The TemplateLogic extension was enforced in the playground as per the US:02 acceptance criteria. This extension helps us in autocomplete and finding out (via regex) which class to instantiate for the sandbox. Therefore, we have an enforcement for this extension in the store.ts. So Yes! we do need this extension validation for the playground.

As for the engine, @Rishabh060105 is right that it currently allows plain classes without failing (could be an accident). To decide if it needs the validation, we'd have to ask ourselves: "do we really want to enforce the TemplateLogic in the engine?". If "yes", then this is a pure bug and we should definately drop the opt-in flag and make the validation unconditional!

@mttrbrts

Copy link
Copy Markdown
Member

The evidence suggests that it's accidental that the engine works for classes that don't extend TemplateLogic class. Let's drop the flag. That greatly simplifies the code. Thanks @Rishabh060105!

Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
@Rishabh060105
Rishabh060105 force-pushed the Rishabh060105/strict-template-logic-validation branch from b6331fa to ab1e662 Compare July 19, 2026 07:11
@Rishabh060105

Rishabh060105 commented Jul 19, 2026

Copy link
Copy Markdown
Author

Hi @mttrbrts, @23harshitkumar I have pushed the changes:

  • Removed the requireTemplateLogic opt-in flag.
  • compileLogic() now always checks that the logic class extends TemplateLogic.
  • Kept the existing compile cache behavior.

Comment thread src/worker.js Outdated
const result = fun(...args);
process.send({ result }, () => {
process.exit();
process.disconnect();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the impact of this change?

@Rishabh060105 Rishabh060105 Jul 19, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially changed this to process.disconnect() because I thought process.exit() was interrupting coverage cleanup.I later realised that process.exit() is viable here since each worker handles one evaluation this means termination must be deterministic after sending the result.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to add stricter (opt-in) validation during TemplateArchiveProcessor.compileLogic() so callers can require that logic/logic.ts defines a class extending TemplateLogic, helping downstream sandbox consumers fail fast during compilation rather than at execution time.

Changes:

  • Adds a TypeScript AST-based check for a TemplateLogic subclass during logic compilation.
  • Refactors the TemplateArchiveProcessor test suite to load templates via a helper and adds new validation-related tests.
  • Adjusts the child-process worker shutdown behavior after sending results/errors.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
test/TemplateArchiveProcessor.test.ts Adds helpers/mocks for loading templates and introduces new compile-time validation/caching tests.
src/worker.js Changes worker termination after process.send() from process.exit() to process.disconnect() (with exit code set on error).
src/TemplateArchiveProcessor.ts Adds a new AST-based TemplateLogic subclass assertion and calls it during TypeScript logic compilation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 113 to +117
if (logicManager.getLanguage() === 'typescript') {
const compiledCode: Record<string, TwoSlashReturn> = {};
const tsFiles: Array<Script> = logicManager.getScriptManager().getScriptsForTarget('typescript');
const logicScript = tsFiles.find((tsFile) => tsFile.getIdentifier() === 'logic/logic.ts');
await this.assertTemplateLogicSubclass(logicScript);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation has been kept unconditional as discussed above.The boolean argument now only controls compilation caching.

expect(validationSpy).toHaveBeenCalledTimes(1);
});

test('should reject plain default-exported classes', async () => {

@Rishabh060105 Rishabh060105 Jul 19, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is based on the agreed behavior.compileLogic() should reject classes that don't extend TemplateLogic without the requirement of an opt-in flag.

Comment thread src/worker.js
Comment on lines 37 to 39
process.send({ result }, () => {
process.exit();
process.disconnect();
});

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed back process.disconnect() to process.exit() and added a test to confirm the same.

Comment thread src/worker.js
Comment on lines 42 to 45
process.send({ message: err.toString() }, () => {
process.exit(1);
process.exitCode = 1;
process.disconnect();
});

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error path now uses process.exit(1),and added a test confirming the original error being returned instead of timeout

Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
@Rishabh060105

Copy link
Copy Markdown
Author

Hi @mttrbrts, I have addressed the latest review feedback:

  • Removed the opt-in flag, compileLogic() now always requires a class extending TemplateLogic.
  • The boolean argument now only controls compilation caching.
  • Changed back process.disconnect() to process.exit()
  • Added tests covering workers with open timers for both success and error paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer-engaged A maintainer has commented or reviewed this item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add strict validation for TemplateLogic subclass in TemplateArchiveProcessor compilation

4 participants